qmtest-2.4.1/0000775000076400007640000000000011122067201012357 5ustar stefanstefanqmtest-2.4.1/LICENSE.OPL0000664000076400007640000000730511110102343014014 0ustar stefanstefanOpen Publication License v1.0, 8 June 1999 I. REQUIREMENTS ON BOTH UNMODIFIED AND MODIFIED VERSIONS The Open Publication works may be reproduced and distributed in whole or in part, in any medium physical or electronic, provided that the terms of this license are adhered to, and that this license or an incorporation of it by reference (with any options elected by the author(s) and/or publisher) is displayed in the reproduction. Proper form for an incorporation by reference is as follows: Copyright (c) 2000, 2001 by CodeSourcery. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License, v1.0. Commercial redistribution of Open Publication-licensed material is permitted. Any publication in standard (paper) book form shall require the citation of the original publisher and author. The publisher and author's names shall appear on all outer surfaces of the book. On all outer surfaces of the book the original publisher's name shall be as large as the title of the work and cited as possessive with respect to the title. II. COPYRIGHT The copyright to each Open Publication is owned by its author(s) or designee. III. SCOPE OF LICENSE The following license terms apply to all Open Publication works, unless otherwise explicitly stated in the document. Mere aggregation of Open Publication works or a portion of an Open Publication work with other works or programs on the same media shall not cause this license to apply to those other works. The aggregate work shall contain a notice specifying the inclusion of the Open Publication material and appropriate copyright notice. SEVERABILITY. If any part of this license is found to be unenforceable in any jurisdiction, the remaining portions of the license remain in force. NO WARRANTY. Open Publication works are licensed and provided "as is" without warranty of any kind, express or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose or a warranty of non-infringement. IV. REQUIREMENTS ON MODIFIED WORKS All modified versions of documents covered by this license, including translations, anthologies, compilations and partial documents, must meet the following requirements: 1. The modified version must be labeled as such. 2. The person making the modifications must be identified and the modifications dated. 3. Acknowledgement of the original author and publisher if applicable must be retained according to normal academic citation practices. 4. The location of the original unmodified document must be identified. 5. The original author's (or authors') name(s) may not be used to assert or imply endorsement of the resulting document without the original author's (or authors') permission. V. GOOD-PRACTICE RECOMMENDATIONS In addition to the requirements of this license, it is requested from and strongly recommended of redistributors that: 1. If you are distributing Open Publication works on hardcopy or CD-ROM, you provide email notification to the authors of your intent to redistribute at least thirty days before your manuscript or media freeze, to give the authors time to provide updated documents. This notification should describe modifications, if any, made to the document. 2. All substantive modifications (including deletions) be either clearly marked up in the document or else described in an attachment to the document. 3. Finally, while it is not mandatory under this license, it is considered good form to offer a free copy of any hardcopy and CD-ROM expression of an Open Publication-licensed work to its author(s). qmtest-2.4.1/ChangeLog0000664000076400007640000146751711122065100014152 0ustar stefanstefan2008-12-16 Stefan Seefeld * setup.py: Bump version number to 2.4.1. * qmtest.spec: New rpm spec-file. * NEWS: Mention 2.4.1 release. * README: Clarify license version. 2008-12-10 Stefan Seefeld * setup.py: Install LICENSE.OPL so it can be found by users. * MAKEFILE.in: Likewise. * doc/qmtest.ent: bump version number to 2.4.1 * qmdist/command/check.py: Fix Python 3k incompatibility. * qmdist/command/build_scripts.py: Likewise. * qm/test/cmdline.py: Likewise. * qm/web.py: Likewise. * qm/platform_unix.py: Likewise. 2008-11-16 Stefan Seefeld * LICENSE.OPL: New file. * doc/qm.mod: Fix OPL license reference. * doc/tutorial.xml: Likewise. * doc/cli_reference.xml: Likewise. * doc/concepts.xml: Likewise. * doc/customizing.xml: Likewise. * doc/extending.xml: Likewise. * templates/docbook-chapter: Likewise. * templates/docbook: Likewise. * doc/design/qmtest/core.xml: Likewise. * doc/design/qmtest/iface.xml: Likewise. * doc/design/qmtest/impl.xml: Likewise. * doc/design/qmtest/qmtest.xml: Likewise. * doc/design/qmtest/refs.xml: Likewise. * doc/design/qmtest/req.xml: Likewise. * share/qmtest/dtml/add-enumeral.dtml: Likewise. * share/qmtest/dtml/attachment.dtml: Likewise. * share/qmtest/dtml/error.dtml: Likewise. * share/qmtest/dtml/exception.dtml: Likewise. * share/qmtest/dtml/field.dtml: Likewise. * share/qmtest/dtml/help.dtml: Likewise. * share/qmtest/dtml/login_form.dtml: Likewise. * share/qmtest/dtml/problems.dtml: Likewise. * share/qmtest/dtml/set.dtml: Likewise. * share/qmtest/dtml/user.dtml: Likewise. 2008-11-13 Stefan Seefeld * qm/external/DocumentTemplate/*: Partially upgrade to Zope 2.11. 2008-10-21 Stefan Seefeld * qm/structured_text.py: Remove python script header. * qm/test/cmdline.py: Report help and version to stdout. 2008-04-09 Stefan Seefeld * qmdist/command/install_lib.py: Remove incorrect use of --root. 2007-09-26 Stefan Seefeld * NEWS: Document new features in version 2.4. * doc/qmtest.ent: Set version number to 2.4. * qm/config.py: Don't hard-code version number. * qmdist/command/build_py.py: ...but compute it at build time. * qmdist/command/install_lib.py: Likewise. * setup.py: Cleanup. * share/qmtest/examples: Move to... * share/doc/qmtest/examples: ...here. 2007-09-25 Stefan Seefeld * MANIFEST.in: Remove obsolete entries. * qm/test/classes/xml_expectation_database.py: Refine. * share/qmtest/examples/tdb: Rename to... * share/qmtest/examples/xml_tdb: ...this. * share/qmtest/examples/compilation_tdb: Add new example test database. * qm/test/classes/previous_testrun.py: Add file_name parameter. * doc/concepts.xml: Document expectation databases. * doc/customizing.xml: Likewise. * qm/test/classes/compiler.py: Add 'ldflags' parameters. * qm/test/classes/compiler_test.py: Add 'compiler' and 'ldflags' parameters to CompilationStep. * qm/test/classes/compilation_test.py: Adjust. * qm/test/classes/compilation_test_database.py: Adjust. * doc/customizing.xml: Adjust. 2007-09-24 Stefan Seefeld * share/qmtest/tutorial: Rename to... * share/qmtest/examples: ...this. 2007-09-20 Stefan Seefeld * qm/test/classes/mount_database.py: Add 'mounts' parameter, fix GetIds() method. * tests/QMTest/configuration: Update MountDatabase configuration. * qm/test/expectation_database.py: Define new extension type. * qm/test/classes/previous_testrun.py: New extension. * qm/test/classes/xml_expectation_database.py: New extension. * qm/test/classes/classes.qmc: Register them. * qm/test/cmdline.py: Support ExpectationDatabase * qm/test/base.py: Likewise. * qm/test/execution_engine.py: Adjust. * qm/test/web/web.py: Adjust. * share/qmtest/dtml/test/dir.dtml: Only make expectations editable if they really are * share/qmtest/dtml/test/results.dtml: Likewise. * qm/fields.py: Various fixes to DictionaryField and SetField. * qm/web.py: Insert correct module search path for local DocumentTemplate package. 2007-09-19 Stefan Seefeld * qm/test/classes/mount_database.py: Add support for 'mounts' parameter, fix GetIds() method. * tests/QMTest/configuration: Adjust. * qm/fields.py: Fix various issues with DictionaryField and SetField. 2007-08-17 Stefan Seefeld * qm/test/classes/python.py: Expect new-style exceptions (python 2.5). 2007-07-03 Stefan Seefeld * qm/test/classes/compilation_test_database.py: New test database class. * qm/test/classes/classes.qmc: Register it. 2007-02-09 Stefan Seefeld * qm/external/DocumentTemplate/*: partially merge in bits from Zope 2.10.1 to replace all uses of the obsolete 'regex' module by 're'. * qm/web.py: Adjust module search path to make 'import DocumentTemplate' work. 2007-01-25 Stefan Seefeld * qmdist/command/__init__.py: Explicitely close the modified file. * qmdist/command/install_lib.py: Force recompilation. 2006-12-12 Mark Mitchell * qm/test/classes/dejagnu_stream.py (DejaGNUReader.__UpdateResult): Treat DejaGNU UNTESTED results as QMTEST UNTESTED results when generating outcomes from a DejaGNU log file. 2006-11-29 Stefan Seefeld * qm/test/target.py: Only delete the 'qmtest.id' context variable if it really exists. 2006-11-23 Stefan Seefeld * qmdist/command/install_lib.py: Force recompilation of generated config.py file. 2006-11-08 Stefan Seefeld * qm/host.py: Adjust constructor to expect keyword arguments. 2006-11-03 Stefan Seefeld * qm/config.py: Provide initial values for config parameters. * qm/__init__.py: Use it. * qm/__version.py: Removed (since now obsolete). * qmdist/command/__init__.py: Add reset_config_variables. * scripts/qmtest-postinstall.py: Use it. * qmdist/command/install_lib.py: Use it. * qmdist/command/install_data.py: Removed (since now obsolete). * qmdist/command/build_py.py: New command; adjusts qm.prefix so it is usable in the build tree. * qmdist/command/build_doc.py: Modularize. * qmdist/command/check.py: Set PYTHONPATH so the right code gets tested. * qmdist/command/__init__.py: Adjust to always use qm.config. * setup.py: Adjust. * qm/test/result_reader.py: Fix fallout from last patch. * tests/xmldb/api.qms/test.qms/fields.qmt: Likewise. 2006-11-02 Stefan Seefeld * qm/extension.py: Enhance handling of parameters and constructor arguments. * qm/test/database.py: Likewise. * qm/test/file_database.py: Likewise. * qm/test/file_result_reader.py: Likewise. * qm/test/file_result_stream.py: Likewise. * qm/test/result_stream.py: Likewise. * qm/test/runnable.py: Likewise. * qm/test/suite.py: Likewise. * qm/test/target.py: Likewise. * qm/test/classes/dejagnu_stream.py: Likewise. * qm/test/classes/pickle_result_stream.py: Likewise. * qm/test/classes/rsh_target.py: Likewise. * qm/test/classes/sql_result_stream.py: Likewise. * qm/test/classes/tet_stream.py: Likewise. * qm/test/classes/text_result_stream.py: Likewise. * qm/test/classes/xml_result_stream.py: Likewise. 2006-10-31 Stefan Seefeld * qm/test/share/*: Merged into... * share/qmtest: ...here. * share/*: Likewise. * setup.py: Simplify. * qmdist/command/install_data.py: Adjust data_path ('qm' -> 'qmtest'). * qm/__init__.py: Simplify. * qm/common.py: Remove obsolete 'is_installed' variable. * qm/diagnostic.py: Likewise. * qm/test/web/web.py: Adjust menu to contain 'Tutorial' in new location. 2006-10-31 Stefan Seefeld * qmdist/command/install_data.py: Set 'prefix' variable. * scripts/qmtest-postinstall.py: Adjust it to actual installation. * qmdist/command/bdist_wininst.py: Use postinstall script. * qmdist/command/install_script.py: Removed (obsoleted). * share/logo.bmp: Some eye-candy for windows installer. * qm/test/qmtest: Move to... * scripts/qmtest: ...here; removed obsolete logic to determine paths. * setup.py: Incorporate all the above changes. * MANIFEST.in: Reflect new script location. * qm/__init__.py: Use correct variables unconditionally. * qmdist/command/build_doc.py: Fix to at least build html even if no fo processor is found. 2006-10-25 Stefan Seefeld * qm/test/classes/command_host.py: New host extension. * qm/test/classes/classes.qmc: Register it. 2006-09-29 Stefan Seefeld * qm/test/classes/compiler_test.py: Fix quoting of command annotation. * qm/fields.py: Add DictionaryField. * qm/test/context.py: Add GetDerivedValue and as_string_list functions. * qm/test/database.py: Prevent redundant instantiation of extension classes. 2006-09-05 Mark Mitchell * qm/executable.py (Executable.Spawn): Search PATH on Windows if appropriate. 2006-09-03 Mark Mitchell * qm/host.py (Host.UploadAndRun): Correct logic for deleting files. 2006-08-18 Stefan Seefeld Reorganize and enhance Tutorial: * qm/doc/tutorial.xml: New file. * qm/doc/qmtest.ent: Likewise. * qm/doc/introduction.xml: Likewise. * qm/doc/cli_reference.xml: Likewise. * qm/doc/concepts.xml: Likewise. * qm/doc/cs.css: Likewise. * qm/doc/html.xsl: Likewise. * qm/doc/qm-opl.xml: XML-ified. * qm/doc/manual/common-manual.xml: Removed. * qmdist/command/build_doc.py: Adjust build procedure for html generation. 2006-08-17 Mark Mitchell * qm/host.py (Host.Run): Add 'relative' parameter. (Host.UploadAndRun): Use it. * qm/test/classes/ssh_host.py (SSHHost.Run): Add 'relative' parameter. * qm/test/cmdline.py (QMTest.__ExecuteSummarize): Display resource results too. * qm/test/doc/reference.xml: Document. 2006-07-17 Stefan Seefeld * qm/test/cmdline.py: Allow 'qmtest create' to create explicit suites, and make their content visible through 'qmtest ls'. 2006-06-21 Stefan Seefeld * qm/test/report.py: Add support for '-' special output file. 2006-06-09 Stefan Seefeld * qm/host.py: Fix signature of Host.Run(), and implement it (using local_host.LocalHost.Run() code). * qm/test/classes/local_host.py: Remove now obsolete Run() method. * qm/test/classes/ssh_host.py: Derive from Host, not LocalHost. 2006-06-02 Stefan Seefeld * qm/extension.py: Raise AttributeError instead of AssertionError when wrong attributes are passed. * qm/common.py: Add parse_string_list function. * qm/test/context.py: Add Context.GetStringList method. * qm/test/classes/compiler.py: Add optional ldflags argument to Compiler constructor. * qm/test/classes/compiler_test.py: Fix _RemoveDirectory() * qm/test/classes/compilation_test.py: Add ExecutableTest. * qm/test/classes/classes.qmc: Adjust compilation_test name changes. 2006-03-07 Stefan Seefeld * qm/test/classes/compiler_table.py: Fix search for host extension to include database-specific path. 2005-12-02 Stefan Seefeld * qm/__init__.py: Define new extension_path variable. * qm/test/base.py: Use it to lookup QMTest extensions. * qm/dist/__init__.py: Provide build infrastructure to install qmtest extensions. * qm/dist/distribution.py: Likewise. * qm/dist/command/__init__.py: Likewise. * qm/dist/command/build_extensions.py: Likewise. * qm/dist/command/install_extensions.py: Likewise. * setup.py: Install it. * qmdist/command/install_data.py: Likewise. 2005-12-01 Mark Mitchell * qm/test/cmdline.py (QMTest.__ExecuteSummarize): Print resource results for UNTESTED tests. * qm/test/classes/compiler_table.py: Provide standard names for the C and C++ programming languages. 2005-11-30 Mark Mitchell * qm/extension.py (get_extension_class_name): Use only the final component of the module in forming the extension class name. * qm/test/database.py (Database.GetIds): Handle generic databases. * qm/test/classes/compiler_test.py (CompilationStep): Provide default values. (CompilerBase._MakeDirectory): Do not create the temporary build directory if it already exists. (CompilerTest.Run): Create the temporary build directory. Record the output from the compiler here. (CompilerTest._GetExecutableArguments): New function. (CompilerTest._MustExecutableExitSuccessfully): New function. (CompilerTest._RunExecutable): Use new functions. (CompilerTest._CheckOutput): Do not record the output here. Adjust use of _DiagnosticsToString. (CompilerTest._CheckExecutableOutput): New function. (CompilerTest._DiagnosticsToString): Add annotation parameter. * qm/test/classes/compiler.py (Compiler.ParseOutput): Do not try to match an error message against multiple severities. * qm/test/result.py (Result.CheckExitStatus): Fix typos. * qm/host.py (Host.UploadAndRun): Delete the file after running it. * qm/test/classes/local_host.py (LocalHost.UploadAndRun): New method. * qm/test/classes/compiler_test.py (CompilerTest._RunExecutable): Do not delete executables after running them. 2005-11-17 Mark Mitchell * qm/test/classes/dejagnu_stream.py (DejaGNUStream.__summary_outcomes): Add KFAIL, KPASS. (DejaGNUStream.__outcome_descs): Likewise. (DejaGNUStream.__expected_outcomes): Likewise. (DejaGNUReader.__UpdateResult): Likewise. * qm/test/classes/dejagnu_test.py (DejaGNUTest.KFAIL): New variable. (DejaGNUTest.KPASS): Likewise. (DejaGNUTest.outcome_map): Add KFAIL, KPASS. 2005-11-16 Stefan Seefeld * qm/test/classes/compiler_table.py: Tolerate whitespace in context file. * qm/test/classes/dejagnu_test.py: Use CompilerTable.target as host. 2005-11-04 Stefan Seefeld * qm/test/test_run.py: Add GetAnnotations() method. * qm/test/reader_test_run.py: Implement it. * qm/test/report.py: Rewrite report generation now supporting two formats. * qm/test/cmdline.py: Add '--flat' option to the 'report' command. * qm/test/doc/reference.xml: Document it. * share/xml/report.xslt: Adjust html-report generation to new format. 2005-11-04 Mark Mitchell * qm/test/classes/dejagnu_stream.py (DejaGNUReader.__NextOutcome): Ignore ERROR results. (DejaGNUReader.__UpdateResult): Don't repeat causes. Don't use causes at all for non-combined results. 2005-10-25 Stefan Seefeld * qm/test/result.py: Add refactored CheckExitStatus method. * qm/test/classes/command.py: Use it. * qm/test/classes/compiler_test.py: Prepare CompilerTest for reuse; general cleanup. * qm/test/classes/compilation_test.py: Add new SimpleCompilationTest and SimpleCompiledResource extensions. * qm/test/classes/classes.qmc: Register them. 2005-10-25 Mark Mitchell * qm/test/classes/dejagnu_stream.py (sets.Set): Don't import it. (DejaGNUReader.__init__): Don't set test_ids. 2005-10-25 Stefan Seefeld * share/xml/report.xslt: Fix handling of multiple test runs. 2005-10-24 Mark Mitchell * qm/test/classes/dejagnu_stream.py (DejaGNUStream.__UpdateResult): Fix typo. * qm/test/classes/dejagnu_stream.py (cgi): Import it. (re): Likewise. (sets.Set): Likewise. (DejaGNUReader): Add combined mode. Add expectations-generation mode. 2005-10-23 Mark Mitchell * qm/test/base.py (load_outcomes): Adjust documentation. (load_results): Permit file parameter to be an extension descriptor. * qm/test/cmdline.py (QMTest.commands_spec): Add --output option to "qmtest summarize". (QMTest.__ExecuteSummarize): Use self.results_file_name. Adjust call to load_results. Pass result of --output option to __GetResultStreams. (QMTest.__ExecuteRun): Use self.results_file_name. Pass results file name to __GetResultStreams. (QMTest.__GetExpectedOutcomes): Adjust call to load_outcomes. (QMTest.__FilterTestsToRun): Likewise. (QMTest.__GetResultStreams): Add output_file parameter. Create a file result stream appropriate. * qm/test/report.py (ReportGenerator._CreateResultStreams): Adjust call to load_results. * qm/test/classes/dir_run_database.py (DirRunDatabase.__init__): Likewise. * qm/test/doc/manual.xml: Use DocBook 4.2. Provide a URL for the DocBook DTD. * qm/test/doc/reference.xml: Document -o option to summarize and extended descriptor syntax for input file. * qm/test/result_stream.py (qm.test.result.Result): Import it. (ResultStream._GetExpectedOutcome): New method. * qm/test/classes/text_result_stream.py (TextResultStream.WriteResult): Use it. (TextResultStream.DisplayResult): Treat Result.CAUSE annotation as HTML. * qm/test/result.py (Result.SetOutcome): Use SetCause. (Result.SetCause): New method. (Result.NoteException): Use SetCause. 2005-10-18 Stefan Seefeld * qm/test/cmdline.py: Fix handling of '.' pseudo-id. * qm/test/web/web.py: Likewise. 2005-10-14 Stefan Seefeld * qm/test/cmdline.py: Add 'annotate' option to 'run' command, refine 'describe' option. 2005-09-14 Stefan Seefeld * qm/test/cmdline.py: Add 'describe' and enhance 'ls' commands. * qm/test/doc/reference.xml: Document the above. * qm/label.py: Fix documentation. * qm/test/database.py: Fix typo. * qm/test/classes/thread_target.py: Clarify trace messages. * qm/test/share/dtml/dir.dtml: Fix typo. * qm/test/share/dtml/navigation-bar.dtml: Enhance menu display. * qm/test/share/dtml/show.dtml: Add missing logo. * share/web/stylesheets/qm.css: Enhance menu display. Add support for inspecting 'run databases': * qm/test/run_database.py: New RunDatabase extension. * qm/test/base.py: Register it. * qm/test/dir_run_database.py: Implement it. * qm/test/classes/classes.qmc: Register implementation. * qm/test/test_run.py: Define TestRun base class. * qm/test/reader_test_run.py: Implement it. * qm/web.py: Allow WebRequest to inherit all fields from its base. * qm/test/cmdline.py: Add -R option to the 'gui' command. * qm/test/web/web.py: Add support for new report pages. * qm/test/share/dtml/report/dir.dtml: New page template. * qm/test/share/dtml/report/show.dtml: New page template. * setup.py: Add new share/dtml/report directory. 2005-09-06 Stefan Seefeld * qm/test/classes/dejagnu_test.py: Fix typo. * qm/test/classes/dg_test.py: Add new 'keep_output' field. 2005-09-02 Mark Mitchell * qm/test/resource_adapter.py: New file. * qm/test/resource.py (resource_adapter): Remove. 2005-09-01 Mark Mitchell * qm/test/resource.py (resource_adapter): New function. 2005-08-23 Mark Mitchell * qm/test/base.py (FileResultReader): Import it. (get_extension_classes): New function. (load_results): Let FileResultReaders decided if they understand the file format, rather than hard-coding the decision here. * qm/test/cmdline.py (QMTest.GetDatabaseIfAvailable): New method. Use it throughout, where appropriate. (QMTest.__ExecuteSummarize): Permit execution without a database. (QMTest.__GetResultStreams): Likewise. * qm/test/file_result_reader.py (FileResultReader.InvalidFile): New class. * qm/test/result_stream.py (ResultStream.arguments): Remove unused "database" argument. * qm/test/classes/classes.qmc: Add dejagnu_stream.DejaGNUReader. * qm/test/classes/dejagnu_test.py (DejaGNUTest.ERROR): Fix typo. (DejaGNUTest.__outcome_map): Rename to ... (DejaGNUTest.outcome_map): ... this. Fill in all entries. (DejaGNUTest._RecordDejaGNUOutcome): Adjust. * qm/test/classes/pickle_result_stream.py (PickleResultReader.__init__): Raise InvalidFile if appropriate. * qm/test/classes/xml_result_stream.py (XMLResultReader.__init__): Likewise. * qm/test/classes/dejagnu_stream.py (DejaGNUReader): New class. 2005-08-19 Stefan Seefeld * MANIFEST.in: Add missing files. 2005-07-22 Mark Mitchell * qm/test/cmdline.py (QMTest.list_long_option_spec): New variable. (QMTest.list_recursive_option_spec): Likewise. (QMTest.commands_spec): Add "ls". (QMTest.Execute): Support "ls". (QMTest.__ExecuteList): New method. * qm/test/datbase.py (Database.GetExtensions): New method. * qm/test/doc/reference.xml: Describe "qmtest ls". 2005-07-21 Stefan Seefeld * setup.py: Adjust contact info. * qm/test/doc/manual.xml: Update copyright notice. 2005-07-21 Mark Mitchell * qm/test/classes/dg_test.py (DGTest._RunDGToolPortion): Fix typo. * qm/extension.py (Extension.GetClassName): New method. (Extension.GetExplicitArguments): Likewise. (Extension.MakeDomEelement): Use GetExplicitArguments. (parse_descriptor): Add extension_loader. * qm/test/cmdline.py (qm.test.runnable.Runnable): Import it. (QMTest.extension_id_option_spec): New variable. (QMTest.conflicting_option_specs): Update. (QMTest.__ExecuteCreate): Support writing extensions to the database. * qm/test/database.py (Database.GetExtension): Fix typo. * qm/test/doc/reference.xml: Document --id option to "qmtest create". * qm/test/share/messages/diagnostics.txt (db not modifiable): New message. (no db specified): Update message. 2005-07-20 Mark Mitchell * qm/test/database.py (qm.test.resource.Resource): Import it. (qm.test.suite.Suite): Likewise. (Database._is_generic_database): New variable. (Database.GetExtension): New function. (Database.GetTest): Use it. (Database.GetResource): Likewise. (Database.GetSuite): Likewise. * qm/test/doc/reference.xml: Update information about writing database classes. * qm/executable.py (Executable.Spawn): Initialize self.__child. (Executable._GetChildPID): Adjust documentation to reflect that this function may return None. (TimeoutExecutable.Run): If the child is None, do not try to kill it. * qm/test/doc/reference.xml: Add documentation about prerequisites. 2005-07-19 Mark Mitchell * qm/test/execution_engine.py (ExecutionEngine.__AddTestToStack): If a test prerequisite does not exist, give the test an error outcome. * qm/test/share/messages/diagnostics.txt (prerequisite not in database): New message. * tests/regress/bad_prereq: New test. * qm/test/classes/python.py (ExecTest.Run): Handle empty input. * qm/test/doc/reference.xml: Provide example of SetUp and CleanUp methods for resources. Revert: 2005-07-19 Mark Mitchell * qm/test/doc/manual.xml: Use DocBook 4.2. * qm/test/doc/manual.xml: Use DocBook 4.2. * qmdist/command/build_doc.py (find_file): Remove. (build_doc.user_options): New variable. (build_doc.xml_dcl_paths): Likewise. (build_doc.dtd_dirs): Likewise. (build_doc.stylesheet_dirs): Likewise. (build_doc.initialize_options): New function. (build_doc.finalize_options): Likewise. (build_doc.call_jade): Remove dcl parameter. Use Jade options provided by the user. (build_doc.run): Honor user direction regarding what documentation to build. (build_doc.find_file): New function. * qm/test/classes/command.py (ShellScriptTest._GetShell): New function. (ShellScriptTest.Run): Use it. * qm/test/file_database.py: Fix typo in documentation. 2005-07-06 Stefan Seefeld * NEWS: Report improvements in version 2.3. 2005-07-05 Mark Mitchell * qm/test/cmdline.py (QMTest.__ExecuteRegister): Fix typo. 2005-06-23 Stefan Seefeld * qm/share/xml/report.xslt: New stylesheet to generate html reports. * setup.py: Fix installation paths. * qm/__version.py: Increment version_info to (2,3,0). * qm/test/cmdline.py: Enhance documentation for 'report' command. * qm/test/file_database.py: Fix typos. * qm/test/result_stream.py: Remove obsolete comment. * qm/test/doc/reference.xml: Document 'report' command. * qm/test/web/web.py: Fix incorrect documentation strings. 2005-06-13 Mark Mitchell * qm/remote_host.py: Rename to ... * qm/host.py: ... this. Replace "RemoteHost" with "Host" throughout. * qm/test/base.py: Adjust accordingly. * qm/test/classes/classes.qmc: Likewise. * qm/test/classes/compiler_table.py: Likewise. * qm/test/classes/local_host.py: Likewise. 2005-06-10 Mark Mitchell * qm/remote_host.py: New file. * qm/test/base.py (__extension_bases): Add "remote_host". (extension_kinds): Derive automatically from __extension_base. * qm/test/classes/classes.qmc: Add local_host.LocalHost, ssh_host.SSHHost, ssh_host.RSHHost, and simulator.Simulator. * qm/test/classes/compiler.py (Compiler.GetExecutableExtension): New method. (Compiler.GetObjectExtension): Likewise. * qm/test/classes/compiler_table.py (CompilerTable.Setup): Fix typos and thinkos. Set up CompilerTable.target. * qm/test/classes/compiler_test.py (CompiledExecutable): Remove. (CompilerTest._GetObjectFileName): Fix typo in comment. (CompilerTest.Run): Save the compiler. (CompilerTest._RunExecutable): Use the RemoteHost provided by the compiler table. * qm/test/classes/local_host.py: New file. * qm/test/classes/simulator.py: Likewise. * qm/test/classes/ssh_host.py: Likewise. * qm/test/cmdline.py (QMTest.__ExecuteRegister): Use __CheckExtensionKind. * qm/test/result.py (Result.NoteException): Quote exception string. * qm/extension.py (Extension.Type.__init__): Fix overlong lines. (make_dom_element): Fix typo in comment. 2005-06-06 Stefan Seefeld * setup.py: Move data into /share/qm. * qm/__init__.py: Likewise. * qmdist/command/install_data.py: Likewise. * MANIFEST.in: Cleanup. * Makefile: Removed. * configure: Removed. * configure.in: Removed. * qm/test/classes/compiler.py: Bugfix and cleanup. 2005-06-01 Mark Mitchell Test documentation generation again. 2005-05-31 Stefan Seefeld * qm/test/report.py: Support expectation files. * qm/test/cmdline.py: Factor out global database and targets objects to... * qm/test/test.py: ...here. * qm/test/database.py: ...and here. * qm/test/context.py: Add TARGET_CONTEXT_PROPERTY. * qm/test/target.py: Define it. * qm/test/classes/command.py: Use unicode context variables when setting up environment, but only when convertible to str. 2005-05-18 Zack Weinberg * qm/test/database.py (ItemDescriptor._Execute): Use getattr and a bound method object instead of eval. 2005-05-03 Stefan Seefeld * qm/test/report.py: Add ReportGenerator module. * qm/test/cmdline.py: Add 'report' command. 2005-04-15 Stefan Seefeld * qm/test/classes/compiler.py: Add support for new 'ldflags' parameter. * qm/test/classes/compiler_table.py: Likewise. 2005-04-14 Stefan Seefeld * qm/test/classes/compiler.py: Moved over extension from qmtc. * qm/test/classes/compiler_table.py: Likewise. * qm/test/classes/compiler_test.py: Likewise. * qm/test/classes/classes.qmc: Registered 'CompilerTable' resource. 2005-03-31 Stefan Seefeld * qm/extension.py: Fix omission (see entry from 2005-03-24). 2005-03-29 Stefan Seefeld * qm/test/parameter_database.py: New file. 2005-03-24 Stefan Seefeld * qm/extension.py: Enhance the detection of argument name collision. * Makefile: Removed. * configure.in: Removed. * configure: Removed. 2005-03-21 Stefan Seefeld * qm/extension.py: Use metaclass to manipulate 'Field' members. * qm/fields.py: Make fields more convenient to use in the context of Extensions. * tests/xmldb/api.xms/test.qms/fields.qmt: New unit test for this feature. * tests/xmldb/QMTest/test_inheritance.py: Adjust test to new feature. * qm/test/classes/python.py: Work around a python bug. * qm/test/classes/command.py: Generalize ExecTestBase's output validation. 2005-03-20 Stefan Seefeld * qm/test/classes/xml_database.py: Fix ExplicitSuite constructor call. * tests/regress/QMTest/selftest.py: Allow an 'ids' file to specify test and suite ids to be specified to be used in the 'qmtest run' command. * tests/regress/xml2: New regression test for XMLDatabase's ability to use explicit suites. * qm/test/share/tutorial/tdb/suite.qms: New demo suite. 2005-02-14 Stefan Seefeld * README: Update documentation to reflect current build procedure. * GNUmakefile.in: Removed. 2005-02-14 Stefan Seefeld * qm/web.py: Replace deprecated use of whrandom by random. * qm/external/DocumentTemplate/DT_Util.py: Likewise. 2005-01-05 Stefan Seefeld * qmdist/command/build_scripts.py: Create new command to extend the default build_scripts command. * setup.py: Use the extended build_scripts command. * GNUmakefile.in: Remove obsolete command. 2004-12-16 Stefan Seefeld * qm/test/web/web.py: Replace operator 'is' by '==' in string comparison 2004-10-28 Matthias Klose * qmdist/command/build_doc.py (build_doc.run): Use "openjade" if "jade" is not available. 2004-08-20 Nathaniel Smith * qm/__init__.py: Don't import or define 'lib_dir'. * qmdist/command/install_data.py (install_data.run): Don't define 'lib_dir'. * qm/common.py (get_lib_directory): Don't use 'lib_dir' and 'qm.prefix', but rather '__file__'. * qm/test/base.py (get_extension_directories): Remove now-redundant logic around call to 'get_lib_directory'. 2004-05-28 Mark Mitchell * qm/test/qmtest (check_python_version): Clarify error message. 2004-05-27 Mark Mitchell * qm/test/qmtest (check_python_version): Rework to avoid using newer Python features. 2004-05-26 Mark Mitchell * MANIFEST.in (qm/test/doc/html/qm.css): Include it. 2004-05-25 Mark Mitchell * qm/test/execution_engine.py (ExecutionEngine._WriteInitialAnnotations): Check that uname is not None before trying to write it out. * qm/test/qmtest (qm.sigmask): Import it in the global scope, not ... (main): ... here. 2004-05-24 Mark Mitchell * NEWS: Mention improvements in 2.2. * GNUmakefile.in (distclean): Remove MANIFEST. * setup.py: Install documentation stylesheet. * doc/qm-sgml.dsl: Use documentation stylesheet. * doc/qm.css: Incorporate bits of CodeSourcery web site look-and-feel. * qmdist/command/build_doc.py (build_doc.run): Copy documentation stylesheet to HTML directory. * qm/test/doc/manual.xml: Update copyright date and version number. 2004-05-24 Nathaniel Smith * qmdist/command/build_doc.py (build_doc.run): Create 'doc/qm-version' file. * doc/qm.mod: Define entity 'qm_version' to its contents. * qm/test/doc/manual.xml (internal_doc_url): Use 'qm_version_entity' in definition. 2004-05-21 Nathaniel Smith * qm/test/target.py (Target.Start): Add instance variable '__order_of_resources'. (Target._FinishResourceSetUp): Record resource setup order in it. (Target.Stop): Use it to determine resource cleanup order. * tests/regress/resource_ordering: New test. 2004-05-21 Nathaniel Smith * Makefile: Switch default copyright date to 2004. * docbook: Likewise. * docbook-chapter: Likewise. * dtml: Likewise. * html: Likewise. * py: Likewise. * xml: Likewise. 2004-05-05 Nathaniel Smith * GNUmakefile.in (build): Force executable bit on scripts in build directory. 2004-05-04 Nathaniel Smith * setup.py: Import 'Extension'. Use it to build qm.sigmask. * qm/sigmask.c: New file. * qm/test/qmtest (main): Import 'qm.sigmask'; call 'qm.sigmask.save_mask'. * qm/executable.py: Import 'qm.sigmask'. (Executable._InitializeChild): Call 'qm.sigmask.restore_mask'. * tests/xmldb/signals_unblocked.qmt: New test. * tests/xmldb/signals_unblocked_tmpdir.qma: New resource. * qmdist/command/check.py (check): Overhaul to respect QMTESTFLAGS and use the correct path to the QMTest executable. * GNUmakefile.in: Use "setup.py check" to run tests. * qm/test/qmtest (rel_libdir): When running out of source tree, use built library. 2004-03-30 Nathaniel Smith * qm/common.py (htmllib): Import it. (StringIO): Likewise. (formatter): Likewise. (html_to_text): New function. * qm/test/classes/text_result_stream.py (TextResultStream._DisplayAnnotations): Use it. (formatter): Don't import it. (htmllib): Likewise. (StringIO): Likewise. (qm.common): Import it. (qm.fields): Likewise. * qm/test/result.py (cgi): Import it. (Result.Quote): New function. (Result.NoteException): Use it. * qm/test/classes/dg_test.py (DGTest._RunDGTest): Likewise. * qm/test/classes/command.py (ExecTestBase.RunProgram): Likewise. * qm/test/classes/dejagnu_base.py (DejaGNUBase._RecordCommandOutput): Likewise. (DejaGNUBase._RecordCommand): Likewise. * tests/regress/QMTest/selftest.py (RegTest.Run): Likewise. * tests/results_files/QMTest/results_file_test.py (ResultsFileTest.Run): Likewise. * qm/test/classes/tet_stream.py (TETStream): Many output enhancements. * qm/test/classes/dg_test.py (DGTest._RunDGTest): Refactor, (DGTest._RunDGToolPortion): ...creating this. (DGTest._RunDGExecutePortion): ...and this. * qm/test/classes/pickle_result_stream.py (types): Import it. (PickleResultStream.WriteAnnotation): Check that annotations are strings. * qm/common.py (get_username): Expand docstring. (get_userid): New function. * qm/test/execution_engine.py (ExecutionEngine._WriteInitialAnnotations): Use it. Disambiguate old "qmtest.run.user" annotation by renaming to "qmtest.run.username". Add "qmtest.run.command_line" annotation. 2004-03-15 Nathaniel Smith * qm/test/target.py (Target._SetUpResource): Fix typo from previous commit. 2004-03-15 Nathaniel Smith * qm/test/base.py (CouldNotLoadExtensionError.__init__): Save 'exc_info' value for later use. * qm/test/target.py (qm.test.base): Import it. (Target._SetUpResource): Check for 'CouldNotLoadExtensionError'. * qm/test/classes/dg_test.py (DGTest._RunDGTest): Clarify comment. Convert to pass tool arguments as a list, not a string. Support 'dg-excess-errors'. (DGTest._RunTool): Convert docstring to describe new argument passing conventions. (DGTest._DGoptions): Convert options immediately from string to list. (DGTest._DGexcess_errors): New method. * qm/test/classes/tet_stream.py (TETStream): Add detailed description of TET/LSB and DejaGNU result codes. Fix mapping between them. * qm/test/classes/dejagnu_test.py (DejaGNUTest.TargetExecutable._StdinPipe): Don't override. (DejaGNUTest.BuildExecutable._StdinPipe): Don't override. 2004-03-02 Mark Mitchell * qmdist/command/install_scripts.py (install_scripts.run): Handle pathnames that contain backslashes correctly. 2004-03-02 Nathaniel Smith * qm/test/classes/dg_test.py (DGTest._RunDGTest): Fix formatting of paths to match DejaGNU. (DGTest._DGBogus): Fix copy/paste error in docstring. (DGTest.__ExpectDiagnostic): Use "" rather than 'None' to denote empty comment, to match DejaGNU. 2004-03-02 Nathaniel Smith * qm/test/classes/explicit_suite.py (arguments): Fix formatting of description for 'is_implicit'. 2004-03-01 Mark Mitchell * qm/executable.py (Executable.Spawn): Under Windows, convert all environment variables to Unicode if any of them are Unicode. * NEWS: Mention this improvement. 2004-02-27 Mark Mitchell * setup.py: Install both "qmtest" and "qmtest.py" on all systems. 2004-02-20 Nathaniel Smith * qm/common.py (format_time_iso): Make argument default to current time. * qm/test/execution_engine.py (ExecutionEngine.Run): Don't pass explicit argument to 'format_time_iso'. (ExecutionEngine._WriteInitialAnnotations): Likewise. * qm/test/target.py (qm.common): Import. (Target.RunTest): Record start and end times. * qm/test/classes/tet_stream.py (TETStream._ExtractTime): New function. (TETStream._WriteTCStart): Use it. (TETStream._WriteDejaGNUResult): Likewise. (TETStream._WriteTestResult): Likewise. 2004-02-19 Nathaniel Smith * qm/common.py (parse_time_iso): New function. * qm/test/classes/tet_stream.py: New file. * qm/test/classes/classes.qmc (tet_stream.TETStream): Add. 2004-02-18 Mark Mitchell * qm/__version.py: Advance to 2.2.0. * qm/executable.py (TimeoutExecutable.Run): Handle failure to locate the executable file robustly under Windows. 2004-02-15 Nathaniel Smith * qm/common.py (open_temporary_file_fd): Change default suffix to empty string. (open_temporary_file): Likewise. * qm/test/classes/command.py (ShellScriptTest.Run): Likewise. 2004-02-14 Nathaniel Smith * qm/common.py (encode_data_as_text): Remove. (decode_data_from_text): Likewise. (format_byte_count): Likewise. (base64): Don't import. (cPickle): Likewise. (cStringIO): Likewise. (dircache): Likewise. (gzip): Likewise. (operator): Likewise. (quopri): Likewise. (socket): Likewise. 2004-02-13 Mark Mitchell * qm/common.py (open_temporary_file_fd): Add suffix parameter. (open_temporary_file): Add mode and suffix parameters. * qm/platform.py (get_shell_for_script): Use /c on Windows. * qm/test/classes/command.py (ShellScriptTest): Make the script have a ".bat" extension on Windows. * NEWS: Mention this fix. 2004-02-11 Nathaniel Smith * qm/fields.py: Use types.StringTypes instead of qm.common.string_types. Also remove tabs. * qm/test/result.py: Likewise. * qm/common.py (string_types): Remove. (Empty): Remove. (MutexError): Remove. (MutexLockError): Remove. (ConfigurationError): Remove. (indent_lines): Remove. 2004-02-11 Nathaniel Smith * qm/common.py: Import getpass. (get_username): New function. * qm/test/execution_engine.py (ExecutionEngine._WriteInitialAnnotations): New method. (ExecutionEngine.Run): Call it. (TerminationRequested): New exception. (ExecutionEngine._RunTests): Raise it when terminating. (ExecutionEngine.Run): Check for exceptions in _RunTests. (ExecutionEngine.RequestTermination): More tracing. (ExecutionEngine.Run): Likewise. (ExecutionEngine._RunTests): Likewise. 2004-02-08 Mark Mitchell * NEWS: Remove "Not yet released" markers from news for 2.1. * qm/test/web/web.py (ShowSuitePage.MakeDeleteScript): Return the result of MakeConfirmationDialog. 2004-02-04 Anders Hasselqvist * qm/fields.py (ChoiceField.FormatValueAsHtml): Make sure there is a name for the field. 2004-01-28 Mark Mitchell * qm/test/classes/explicit_suite.py (ExplicitSuite.is_implicit): Give it a default value of false. (ExplicitSuite.IsImplicit): Fix thinko. * qm/test/classes/xml_database.py (XMLDatabase._GetSuiteFromPath): 2004-01-18 Mark Mitchell * qm/test/cmdline.py (_version_output): Add 2004 to list of copyright dates. 2004-01-15 Mark Mitchell * qm/test/classes/xml_database.py (XMLDatabase.__MakeDataFilePath): Use a relative, rather than absolute, path for the file location. 2004-01-14 Mark Mitchell * qm/attachment.py (Attachment.Move): New method. (AttachmentStore.Store): Do not return a value. (TemporaryAttachmentStore.Store): Do not check is_temporary_location. (is_temporary_location): Remove. (make_dom_node): Do not check is_temporary_location. * qm/extension.py (Extension.MakeDomElement): Remove debugging code. * qm/fields.py (Field.GetSubfields): New method. (Field.ParseFormValue): Take a dictionary of attachment stores as a parameter, not a single attachment store. (TextField.ParseFormValue): Likewise. (TupleField.GetSubfields): New method. (TupleField.ParseFormValue): Take a dictionary of attachment stores as a parameter, not a single attachment store. (SetField.GetContainedField): Remove. (SetField.GetHelp): Adjust. (SetField.GetSubfields): New method. (SetField.MakeDomNodeForValue): Do not use GetContainedField. (SetField.ParseFormValue): Likewise. Take a dictionary of attachment stores as a parameter, not a single attachment store. (UploadAttachmentPage.__next_temporary_location): Remove. (UploadAttachmentPage.__init__): Add attachment_store parameter. (AttachmentField.FormatValueAsHTML): Encode the attachment store. (AttachmentField.ParseFormValue): Decode it. * qm/web.py (WebServer.__init__): Create a temporary attachment store. (WebServer.GetTemporaryAttachmentStore): New method. * qm/test/runnable.py (Runnable.GetAttachments): New method. (Runnable.__GetAttachments): Likewise. * qm/test/classes/xml_database.py (XMLDatabase.__StoreAttachments): Rewrite. * qm/test/web/web.py (QMTestServer.__init__): Do not create a temporary attachment store. (QMTestServer.HandleSubmitItem): Pass all available attachment stores to ParseFormValue. Do not try to remove unused attachments here. * share/dtml/attachment.dtml: Encode the attachment store id. 2004-01-13 Stefan Seefeld * qm/test/file_database.py: Fix little bug. 2004-01-12 Mark Mitchell * qm/test/share/dtml/show.dtml: Add is_new field to form. * qm/test/web/web.py (QMTestServer.HandleShowItem): Pass a correct value for "new" to ShowItemPage. * qm/test/classes/python.py (BaseExceptionTest.Run): Use has_exception_argument to keep track of whether or not an argument was provided. (BaseExceptionTest.CheckArgument): Use it. (ExceptionTest.CheckArgument): Likewise. Handle the case of a class that does not provide the "args" interface. * tests/regress/exception_test/arg1.qmt: New test. 2004-01-08 Mark Mitchell * qm/test/doc/reference.xml: Fix typo. 2004-01-02 Mark Mitchell * qm/extension.py (Extension.MakeDomElement): New method. (Extension.MakeDomDocument): Likewise. (Extension.Write): Likewise. * qm/test/base.py (extension_kinds): Add "suite". (qm.test.suite): Import it. (__extension_bases): Mention "suite". * qm/test/datbase.py (Database.WriteTest): Remove. (Database.RemoveTest): Likewise. (Database.WriteResource): Likewise. (Database.RemoveResource): Likewise. (Database.WriteSuite): Likewise. (Database.RemoveSuite): Likewise. (Database.IsModifiable): Adjust comment. (Database.RemoveExtension): New method. (Database.WriteExtension): Likewise. * qm/test/directory_suite.py (DirectorySuite.__init__): Adjust for the fact that 'Suite' is now an 'Extension. (DirectorySuite.IsImplicit): New method. * qm/test/file_database.py (FileDatabase.RemoveTest): Remove. (FileDatabase.RemoveResource): Likewise. (FileDatabase.RemoveSuite): Likewise. (FileDatabase._GetPath): New method. (FileDatabase._RemoveEntity): Remove. (FileDatabase.RemoveExtension): New test. * qm/test/suite.py (Suite): Derive from Extension. * qm/test/classes/explicit_suite.py: New file. * qm/test/classes/classes.qmc: Regenerate. * qm/test/classes/mount_database.py (MountedSuite.__init__): Adjust for the fact that 'Suite' is now an 'Extension. (MountedSuite.IsImplicit): New method. * qm/test/clasess/xml_database.py (XMLDatabase.WriteTest): Remove. (XMLDatabase.WriteResource): Likewise. (XMLDatabase.WriteSuite): Likewise. (XMLDatabase.__StoreAdjustments): Rework to adjust for the fact that actual extension instances are provided. (XMLDatabase._GetSuiteFromPath): Deal with old and new suite formats. (XMLDatabse.WriteExtension): New method. * qm/test/doc/reference.xml: Do not mention WriteTest or RemoveTest. * qm/test/web/web.py (QMTestServer.HandleCreateSuite): Adjust for changes above. (QMTestServer.HandleDeleteItem): Likewise. (QMTestServer.HandleDeleteSuite): Likewise. (QMTestServer.HandleSubmitItem): Likewise. 2003-12-03 Mark Mitchell * setup.py: Use glob expressions for documentation. * doc/qm-sgml.dsl: Do not produce a manifest. * qmdist/command/build_doc.py (build_doc.run): Tidy. * qmdist/command/install_data.py (glob): Import it. (types.StringType): Likewise. (install_data.initialize_options): New method. 2003-11-28 Mark Mitchell * qm/test/file_database.py: Remove misleading comments about methods that cannot be overridden. 2003-11-24 Mark Mitchell * qm/common.py (fnctl): Import it. (close_file_on_exec): New method. * qm/executable.py (qm.common): Import it. (Executable.Run): Use close_file_on_exec. (Executable._MakeCloseOnExec): Remove. (RedirectedExecutable._CreatePipe): Use close_file_on_exec. * qm/test/file_result_stream.py (qm.common): Import it. (FileResultStream.__init__): Use close_file_on_exec. 2003-11-24 Mark Mitchell * GNUmakefile.in (QM_TOOLS): Do not set it. (clean): Remove generated documentation. (distclean): Do not remove qm/__version.py. * MANIFEST.in: Include GNUmakefile.in, configure.in, and configure. * config.guess: Remove. * install-sh: Likewise. * configure.in (QM_MAJOR_VER): Do not AC_SUBST it. (QM_MINOR_VER): Likewise. (QM_RELEASE_VER): Likewise. (QM_VERSION): Likewise. * configure: Regenerated. * version: Remove. * qm/__version.py.in: Likewise. * qm/__version.py: New file. * qm.spec.in: Remove. * .cvsignore: Remove qm.spec. * GNUmakefile.in (distclean): Do not remove qm.spec. * configure.in: Do not generate it. 2003-11-24 Stefan Seefeld * qm/test/result.py: Replace 'property' by 'annotation'. * qm/test/share/dtds/result.dtd: Likewise. 2003-11-23 Mark Mitchell * setup.py: Tidy up. Use "qmtest.py" as the name of the main script under Windows. * qm/__init__.py: Do not honor qm.config settings under Windows. * qm/test/.cvsignore: Add qmtest.py. * qm/test/execution_engine.py (ExecutionEngine.IsTerminationRequested): Rename to .. (ExecutionEngine._IsTerminationRequested): ... this. * qm/test/execution_thread.py (ExecutionThread.IsTerminationRequested): Rename to .. (ExecutionEngine._IsTerminationRequested): ... this. * qm/test/qmtest: Do not honor rel_libdir on Windows. * qm/test/clasess/pickle_result_stream.py (PickleResultStream._is_binary_file): Set it. * qm/test/doc/tour.xml: Update for changes in installation procedures. * qmdist/command/install_scripts.py (install_scripts.run): Process both the "qmtest" and the "qmtest.py" script. * scripts/qm-release: Remove. * .cvsignore: Add build, dist, and MANIFEST. * MANIFEST.in: Update for recent changes. * setup.py: Put qm/test/classes in lib, not share. Add more metadata. Correct documentation handling. * qm/__init__.py: Import lib_dir from qm.config. * common.py (get_lib_directory): New function. * qm/test/base.py (get_extension_directories): Use get_lib_directory, not get_share_directory. * qm/test/clases/__init__.py: New file. * qmdist/.cvsignore: Likewise. * qmdist/command/.cvsignore: Likeiwse. * qmdist/command/__init__.py (get_relative_path): Robustify. * qmdist/command/build.py: New file. * qmdist/command/build_doc.py (build_doc.call_jade): Put generated files in the source directory. (build_doc.run): Update accordingly. * qmdist/command/install_data.py (install_data.run): Set lib_dir in config.py. * qmdist/command/install_lib.py: New file. * qmdist/command/install_scripts.py: Generalize prefix handling. 2003-11-19 Mark Mitchell * test/regress/xml1/asdfasdf.qmt: Do not hard-code path to test. * test/regress/xml1/fnord.qmt: Do not hard-code path to true. * qm/test/doc/reference.xml: Improve documentation for "qmtest create". 2003-11-13 Jeffrey D. Oldham * qm/test/context.py (Context.GetBoolean): Correctly support the default. 2003-11-13 Jeffrey D. Oldham * qm/test/context.py (Context.GetBoolean): Fix typos in introductory comment. Modify documentation of 'default' parameter. Use 'default' parameter. 2003-11-12 Mark Mitchell * qm/test/context.py (Context.DB_PATH_CONTEXT_PROPERTY): New variable. (Context.ID_CONTEXT_PROPERTY): Likewise. (Context.TMPDIR_CONTEXT_PROPERTY): Likewise. * qm/test/target.py (Target.RunTest): Set them. (Target._FinishResourceSetUp): Clear ID_CONTEXT_PROPERTY. (Target._SetUpResource): Set ID_CONTEXT_PROPERTY. * qm/common.py (parse_boolean): New function. * qm/fields.py (BooleanField.Validate): New method. * qm/test/context.py (ContextException.__init__): Generalize. (Context.GetBoolean): New method. * qm/test/result.py (Result.NoteException): Simplify. * qm/test/share/messages/diagnostics.txt (invalid boolean context var): New message. (missing context variable): Likewise. * qm/common.py (open_temporary_file): Fix typo. 2003-11-10 Mark Mitchell * qm/test/qmtest: If SIGINT is received, make sure that our exit code reflects that fact. * qm/test/classes/text_result_stream.py (TextResultStream._FormatStatistics): Robustify. * qm/test/classes/text_result_stream.py (TextResultStream.arguments): Add statistics_format. (TextResultStream._DisplayArguments): Do not write out the heading here. Honor the statistics_format, if provided. (TextResultStream._SummarizeTestStats): Use _FormatStatistics. (TextResultStream._SummarizeRelativeTestStats): Likewise. (TextResultStream._FormatStatistics): New function. 2003-11-09 Mark Mitchell * GNUmakefile.in (.PHONY): Add build and doc. (build): New target. (doc): Likewise. (check-serial): Depend on build, not all. (check-threads): Likewise. (check-processes): Likewise. (check-rsh): Likewise. * qm/temporary_directory.py (sys): Import it. * GNUmakefile.in (DOCUMENTATION): Set value to MAINTAINER_MODE. (TIDY): Likewise. (TIDYFLAGS): Likewise. * configure.in: Do not search for Jade, tidy, DocBook stylesheets, etc. * configure: Regenerated. 2003-10-15 Mark Mitchell * qm/fields.py (SetField.ParseFormValue): Correct logic determining whether or not to redisplay the form. 2003-10-14 Mark Mitchell * GNUmakefile.in: Sipmlify drastically, relying on distutils to do all of the work. * setup.py: Tidy. Add support for DTML files and other missing GUI functionality. * qm/__init__.py: Pull in data_dir from the configuration file. * qm/common.py (get_share_directory): Use it. (get_doc_directory): Likewise. * qm/qm.sh: Remove. * qm/test/.cvsignore: Remove qmtest and qmtest.bat. * qm/test/base.py (get_extension_directories): Use get_share_directory to find test classes. * qm/test/cmdline.py (QMTest.__init__): Add 'path' argument. * qm/test/qmtest.py: Rename to ... * qm/test/qmtest: ... this. Add logic to allow QMTest to find its own modules. * qm/test/doc/reference.xml: Remove QM_PYTHON. * qmdist/command/__init__.py (get_relative_path): New function. * qmdist/command/check.py: Revise to reference "qmtest", not "qmtest.py". * qmdist/command/install_data.py (install_data.run): Output data_dir as a relative path. * qmdist/command/install_scripts.py: New file. * NEWS: Update. 2003-10-02 Stefan Seefeld * qm/test/share/dtds/result.dtd: Convert 'outcome' to an attribute. * qm/test/result.py: Likewise. * qm/test/classes/xml_result_stream.py: Likewise. * tests/results_files/README: Report new xml result file format. * tests/results_files/xml_results_v3.qmr: New reference results file. 2003-10-02 Mark Mitchell * qm/test/base.py (get_extension_directories): Use ";" as the QMTEST_CLASS_PATH separator on Windows. * NEWS: Mention recent improvements. 2003-09-30 Stefan Seefeld * qmdist/command/check.py: New file. * setup.py: Register new check command. 2003-09-28 Mark Mitchell * GNUmakefile.in ($(SCRIPTS)): Don't set QM_BUILD. * qm/__init__.py: Set common.is_installed. * qm/common.py (get_share_directory): Don't use QM_BUILD. (get_doc_directory): Likewise. (is_installed): New variable. * qm/diagnostic.py (__diagnostic_set): New variable. (__help_set): Likewise. (get_diagnostic_set): New function. (get_help_set): Likewise. (message): Use them. (error): Likewise. (warning): Likewise. (load_messages): Likewise. (__initialize_module): Remove. (diagnostic_set): Likewise. (help_set): Likewise. * qm/qm.sh: Eliminate QM_BUILD. * qm/web.py (make_help_link): Use diagnostic.get_help_set(). * qm/test/web/web.py (DefaultDtmlPage.__init__): Don't use QM_BUILD. * qmdist/command/install_data.py (install_data.run): Simplify. * doc/qm-opl.xml: Remove Software Carpentry references. * doc/manual/common-manual.xml: Likewise. * qm/test/doc/manual.xml: Update version number. * qm/test/doc/reference.xml: Remove documentation for non-existant --summary and --no-summary options to "qmtest run". Fix typo in -O documentation for "qmtest summarize". Improve --pid-file documentation. * qm/test/classes/pickle_result_stream.py (PickleResultReader.__init__): Treat cPickle.UnpicklingError like EOFError. * qm/test/cmdline.py (QMTest.summary_formats): Rearrange order. (QMTest.commands_spec): Automatically generate lists of --format options. * qm/test/classes/text_result_stream.py (TextResultStream.arguments): Specify valid enumerals for format. * qm/test/cmdline.py (commands_spec): Add --help support for "qmtest remote". 2003-09-26 Mark Mitchell * qm/executable.py (Executable.Kill): Fix typo. 2003-09-25 Mark Mitchell * qm/test/classes/command.py (ExecTestBase.arguments): Improve documentation for exit_code. * qm/test/doc/tour.xml: Remove discussion of carriage-returns in execution tests. * qm/executable.py (Executable.Kill): New method. (Executable._GetChildPID): Improve documentation. (TimeoutExecutable): Update documentation about timeouts on Windows. (TimeoutExecutable.__init__): Do not ignore timeouts on Windows. (TimeoutExecutable._HandleChild): Create a monitoring thread on Windows. (TimeoutExecutable.Run): Wiat for the monitoring thread to exit. (TimeoutExecutable.__Monitor): New method. 2003-09-21 Mark Mitchell * qm/xmlutil.py (get_children): Remove. (get_child_texts): Don't use it. * qm/test/base.py (get_extension_class_names_in_directory): Support new class directory format. * qm/test/cmdline.py (QMTest.__ExecuteRegister): Generate the class directory using the new directory format. * qm/test/database.py (load_database): Do not use get_children. * qm/test/result.py (Result.MakeDomNode): Revise result format. (__all__): New variable. * qm/test/classes.qmc: Regenerated. * qm/test/classes/xml_result_stream.py (XMLResultStream.WriteAnnotation): Use indentation when writing out results. (XMLResultStream.WriteResult): Likewise. (XMLResultReader._get_result_from_dom): Rename to ... (XMLResultReader._GetResultFromDomNode): ... this. Support old and new formats. * qm/test/share/dtds/result.dtd: Update. * qm/test/share/dtds/class-directory.dtd: Likewise. 2003-09-16 Stefan Seefeld * qmdist/command/install_data.py: Do not generate data_dir, as this isn't reliable (windows installer). * qm/__init__.py: Do not use predefined data_dir. * qm/test/qmtest.py: Deduce data_dir from sys.argv[0]. 2003-09-15 Mark Mitchell * qm/extension.py (make_dom_document): Simplify. * qm/user.py (XmlDatabase.Write): Likewise. * qm/xmlutil.py (make_system_id): Use CodeSourcery URLs. (make_public_id): New function. (create_dom_document): Compute full system and public identifiers here. * qm/test/base.py (dtds): Remove. * qm/test/cmdline.py (QMTest.__ExecuteCreateTarget): Adjust call to create_dom_document. (QMTest.__ExecuteRegister): Likewise. * qm/test/classes/xml_database.py: Likewise. * qm/test/classes/xml_result_stream.py: Likewise. 2003-09-14 Mark Mitchell * qm/executable.py (TimeoutExecutable.__init__): Ignore timeouts under Windows. Accept any representation of "timeout" that can be converted to a float. (__all__): Define. * qm/test/cmdline.py (QMTest.__init__): Improve documentation. 2003-09-12 Mark Mitchell * qm/executable.py (Executable._MakeCloseOnExec): Deal with missing fcntl.FD_CLOEXEC. 2003-09-09 Stefan Seefeld * setup.py: Factor out commands into ... * qmdist/command/build_doc.py: ...this * qmdist/command/install_data.py: ...and this. * qmdist/__init__.py: New file. * qmdist/command/__init__.py: New file. * MANIFEST.in: Provide file list for source distribution. 2003-09-07 Mark Mitchell * qm/fields.py (cStringIO): Do not import. (StringIO): Import. (tokenize): Import. (Field.FormatValueAsText): Use StringIO. (Field.ParseTextValue): Improve documentation. (SetField.FormatValueAsText): Make output match format expected by ... (SetField.ParseTextField): ... this new method. * qm/test/cmdline.py (QMTest.attribute_option_spec): Generalize help text. * share/diagnostics/common.txt (invalid set value): New message. * NEWS: Mention correction of critical resource defect. 2003-09-05 Mark Mitchell * qm/qm.sh (PYTHONPATH): Break "export PTYHONPATH=..." into two statements. 2003-08-29 Mark Mitchell * qm/test/target.py (Target.__init__): Do not set __resources. (Target.Start): Initialize __resources. (Target.Stop): Remove entries created by Target.Start. * GNUmakefile.in (check): Remove dependency on check-rsh. * README: Mention Win32 extensions and update reference to ZPL. * qm/external/DocumentTemplate/LICENSE.txt: New file. 2003-08-28 Stefan Seefeld * setup.py: Make documentation compliant with qmtest's standard. (qm_build_doc): Tidy up the code and make it more clear. (qm_build_doc): Use os.path.join and os.path.normpath for better portability. 2003-08-27 Stefan Seefeld * setup.py: Add build_doc command. 2003-08-27 Stefan Seefeld * setup.py: New file. * qm/__init__.py: Import qm.config for data path and version info. * qm/test/base.py: Add config.data_dir + '/test/classes' to search path. * qm/test/qmtest.py: Insert magic number so this becomes a real script. 2003-08-27 Mark Mitchell * qm/test/web/web.py (LoadContextPage.prompt): Fix quoting. 2003-08-20 Mark Mitchell * qm/test/cmdline.py (QMTest.__ExecuteCreate): Return 2 for failure, not 1. (QMTest.__ExecuteCreateTdb): Likewise. (QMTest.__ExecuteCreateTarget): Likewise. (QMTest.__ExecuteExtensions): Likewise. (QMTest.__ExecuteRegister): Likewise. (QMTest.__ExecuteSummarize): Return 2 when a test fails, not 1. (QMTest.__ExecuteRun): Likewise. * qm/test/qmtest.py: Use 2 as the default exit code, not 1. * qm/test/doc/reference.xml: Update accordingly. * NEWS: Mention documentation of exit status. * qm/test/cmdline.py (QMTest.Execute): Use the return value from __ExecuteCreateTdb. (QMTest.__ExecuteCreate): Return a value explicitly. (QMTest.__ExecuteCreateTdb): Likewise. (QMTest.__ExecuteCreateTarget): Likewise. (QMTest.__ExecuteSummarize): Likewise. (QMTest.__ExecuteRun): Likewise. * qm/test/qmtest.py: Simplify handling of exit codes. * qm/test/classes/mount_database.py: Fix typo in doc-string. * qm/test/doc/reference.xml: Document exit status. 2003-08-18 Nathaniel Smith * qm/common.py (verbose): Remove variable. * qm/test/cmdline.py (QMTest.verbose_option_spec): Remove. (QMTest.global_options_spec): Remove 'verbose_option_spec'. (QMTest.Execute): Don't set 'qm.common.verbose'. * qm/test/doc/reference.xml: Don't document -v/--verbose switch. 2003-08-14 Nathaniel Smith * qm/executable.py (Executable.Spawn): Remove __has_*_run variables. (Executable._InitializeParent): Likewise. (Executable._HandleChild): Likewise. (Executable._InitializeChild): Likewise. (Executable._DoParent): Likewise. * qm/platform_win32.py (get_user_name): Remove. * qm/platform_unix.py (send_email): Remove. (get_user_name): Remove. * qm/regression_test.py: Remove file. * qm/test/doc/reference.xml (Field Classes): Fix typo. * qm/test/file_result_stream.py (FileResultStream.__init__): Fix indentation. 2003-08-14 Nathaniel Smith * qm/executable.py (TimeoutExecutable._HandleChild): Close all fds in the monitor process. * tests/xmldb/test.qms/classes.qms/scripttest_closes_stdin.qmt: New test. 2003-08-14 Nathaniel Smith * qm/executable.py (RedirectedExecutable._InitializeChild): Fix indentation. 2003-08-14 Mark Mitchell * qm/executable.py (TimeoutExecutable.__init__): Document -2 value for timeout. (TimeoutExecutable._InitializeChild): Create the monitor pid in the -2 case as well. (TimeoutExectuable.Run): Kill the entire process group, not just the monitor pid. (TimeoutExectuable.__UseSeparateProcessGroupForChild): New method. (Filter.__init__): Adjust documentation of timeout parameter. * qm/test/classes/command.py (ExecTestBase.RunProgram): Pass -2 to Filter when no timeout is specified. 2003-08-14 Nathaniel Smith * qm/executable.py (Executable._MakeCloseOnExec): New function. (Executable.Run): Use it. (RedirectedExecutable._CreatePipe): Use it; document that fds will be closed on exec. (RedirectedExecutable._InitializeChild): Close all pipe fd's. 2003-08-13 Nathaniel Smith * qm/executable.py (Executable): Typo in docstring. 2003-08-12 Mark Mitchell * qm/test/classes/text_result_stream.py (TextResultStream.WriteResult): Don't save results when using the "stats" format. 2003-08-11 Mark Mitchell * qm/test/classes/command.py (ExecTestBase.RunProgram): Use the exit code returned by Filter.Run on Windows. 2003-08-11 Mark Mitchell * qm/platform_unix.py (SignalException.__init__): Tweak message formatting. (_initialize): Tidy. * qm/test/execution_engine.py (ExecutionEngine._RunTests): Honor termination requests. * qm/test/target.py: Import qm.platform and signal. (Target.RunTest): Honor temination requests in the form of SIGTERM. 2003-08-11 Nathaniel Smith * qm/test/classes/command.py (ExecTestBase.MakeEnvironment): Replace "." with "__" when turning context keys into environment variables. Document in class docstring. (ExecTest.Run): Fix indentation. * qm/test/doc/reference.xml: Document new handling of context variables with "."s in them. * tests/regress/QMTest/selftest.py: Import os.path. Add more documentation. (RegTest.Run): Check for a context file, and if one is found, use it. * tests/regress/env_context1: New directory. * tests/regress/env_context1/QMTest: New directory. * tests/regress/env_context1/QMTest/configuration: New file. * tests/regress/env_context1/context: New file. * tests/regress/env_context1/results.qmr: New file. * tests/regress/env_context1/exectest_nodot.qmt: New file. * tests/regress/env_context1/exectest_dot.qmt: New file. * tests/regress/env_context1/shellcommandtest_nodot.qmt: New file. * tests/regress/env_context1/shellcommandtest_dot.qmt: New file. * tests/regress/env_context1/shellscripttest_nodot.qmt: New file. * tests/regress/env_context1/shellscripttest_dot.qmt: New file. 2003-08-10 Nathaniel Smith * qm/common.py (get_lib_directory): Remove. (get_share_directory): Move path lookup logic to here from setup_path.py. Clarify docstring. (get_doc_directory): Move path lookup logic to here from setup_path.py. Clarify docstring. * qm/setup_path.py: Remove file. * qm/test/qmtest.py: Don't execfile setup_path.py. * GNUmakefile.in ($(SCRIPTS)): Don't set QM_TRUE_LIBDIR. * qm/qm.sh: Don't set QM_TRUE_LIBDIR. 2003-08-10 Nathaniel Smith * qm/version.py.in: Rename to... * qm/__version.py.in: ...this. * qm/__init__.py: Adjust for new name. * qm/.cvsignore: Likewise. * qm/GNUMakefile.in: Likewise. * qm/configure.in: Likewise. * qm/configure: Regenerate. 2003-08-10 Nathaniel Smith * qm/version.py.in: New file. * qm/setup_path.py.in: Remove version handling, and rename to... * qm/setup_path.py: ...this. * qm/.cvsignore: Add version.py, remove setup_path.py. * configure.in (AC_OUTPUT): Munge qm/version.py.in instead of qm/setup_path.py.in. * configure: Regenerate. * GNUmakefile.in (all): Remove qm/setup_path.py. (distclean): Delete qm/version.py, don't delete qm/setup_path.py. * qm/__init__.py: Import version, version_info from qm.version. * qm/test/qmtest.py (main): Don't pass version to QMTest initializer. * qm/test/cmdline.py (QMTest.__init__): Don't accept or record version information. (QMTest.GetVersion): Remove. (QMTest.Execute): Don't call QMTest._GetVersionString. (QMTest._GetVersionString): Remove. 2003-08-08 Nathaniel Smith * qm/test/context.py (ContextException.__safe_for_unpickling__): Set to 1. (ContextWrapper): New class. * qm/test/result.py (Result.__setstate__): New method. (Result.__getstate__): New method. * tests/results_files: New directory. * tests/results_files/QMTest: Likewise. * tests/results_files/QMTest/configuration: New file. * tests/results_files/QMTest/classes.qmc: New file. * tests/results_files/QMTest/results_file_database.py: New file. * tests/results_files/QMTest/results_file_test.py: New file. * tests/results_files/README: New file. * tests/results_files/xml_results.qmr: New file. * tests/results_files/result_class_v0-file_format_v0-pickling_format_v0.qmr: New file. * tests/results_files/result_class_v1-file_format_v0-pickling_format_v0.qmr: New file. * tests/results_files/result_class_v1-file_format_v1-pickling_format_v0.qmr: New file. * tests/results_files/result_class_v1-file_format_v1-pickling_format_v1.qmr: New file. * tests/results_files/tdb: New directory. * tests/results_files/tdb/QMTest: New directory. * tests/results_files/tdb/QMTest/configuration: New file. * tests/results_files/tdb/pass.qmt: New file. * tests/results_files/tdb/fail.qmt: New file. * tests/results_files/tdb/error.qmt: New file. * tests/results_files/tdb/untested.qmt: New file. * tests/results_files/tdb/tmpdir_resource.qma: New file. * tests/results_files/tdb/fail_with_tmpdir.qmt: New file. 2003-08-07 Nathaniel Smith Mark Mitchell * qm/test/execution_engine.py: Improve documentation. (ExecutionEngine.__TARGET_IDLE): New variable. (ExecutionEngine.__TARGET_BUSY): Likewise. (ExecutionEngine.__TARGET_STARVING): Likewise. (ExecutionEngine.__num_idle_targets): Replace with... (ExecutionEngine.__has_idle_targets): ...this. (ExecutionEngine._RunTests): Incorporate above changes. (ExecutionEngine.__AddResult): Likewise. (ExecutionEngine.__AddToTargetPatternQueue): Fix typo. * GNUMakefile.in (check-threads): Set new context variable qmtest_target. (check-processes): Likewise. (check-rsh): Likewise. * qm/qm.sh: Correct handling of QM_PATH when both QM_HOME and QM_BUILD are set. * tests/regress/QMTest/selftest.py (RegTest.Run): Use context variable qmtest_target if defined. * tests/regress/bad_target1/bad_target.qmt: Use a target group that does not match the empty string. * tests/regress/bad_target2/bad_target.qmt: Use a target group that does not match the empty string. * qm/test/classes/xml_database.py: Do not import dircache. * scripts/qm-release: Improve snapshot generation. 2003-08-06 Mark Mitchell * scripts/qm-release: Add support for snapshot releases. 2003-08-01 Mark Mitchell * qm/test/base.py (split_results_by_expected_outcome): Remove. * qm/test/cmdline.py (QMTest.__GetResultStreams): Remove test_suites parameter. * qm/test/result_stream.py (ResultStream.arguments): Remove suite_ids. * qm/test/classes/text_result_stream.py (TextResultStream.__init__): Do not save test and resource results. (TextResultStream.WriteResult): Update outcome counts, but do not save results. (TextResultStream.Summarize): Adjust accordingly. (TextResultStream._SummarizeTestStats): Remove results parameter. (TextResultStream._SummarizeRelativeTestStats): Likewise. (TextResultStream._CountOutcomes): Remove. (TextResultStream._SummarizeTestSuiteStats): Remove. 2003-07-31 Nathaniel Smith Mark Mitchell * qm/test/execution_engine.py: Rewrite to improve scalability. * test/regress/bad_target1: New test. * test/regress/bad_target2: Likewise. * test/regress/nocycle1: Likewise. * test/regress/nocycle2: Likewise. * benchmarks/throughput: New benchmark. * qm/test/classes/text_result_stream.py (TextResultStream): Fix typo in documentation. * qm/test/doc/tour.xml: Update instructions to match GUI changes. 2003-07-30 Mark Mitchell * NEWS: Recommend Mozilla, even on Windows. Mention use of line-ending independent comparisons in "command" test classes. * qm/fields.py (IntegerField.FormatValueAsHtml): Insert space before tag closing. (TextField.FormatValueAsHtml): Likewise. (TextField.ParseFormValue): Correct typo in comment. (TupleField.FormatValueAsHtml): Pretty-print. (SetField.FormatValueAsHtml): Likewise. (AttachmentField.FormatValueAsHtml): Insert space before tag closing. (EnumerationField): Derive from ChoiceField. * qm/web.py (DtmlPage.GenerateXMLHeader): Change encoding field to match that used in generated HTML. (make_select): Remove. * qm/test/classes/command.py (ExecTestBase.Run): Use __CompareText. (ExecTestBase.__CompareText): New method. * qm/test/share/dtml/navigation-bar.dtml: Use "javascript: void(0)" as a go-nowhere URL. * qm/test/share/dtml/show.dtml: Embed the id as a hidden field. * qm/test/web/web.py (ShowItemPage.MakeSubmitUrl): Do not encode the id in the URL. 2003-07-29 Mark Mitchell * GNUmakefile.in (RELLIBDIR): Set correctly under Windows. (PYTHON_PKG_PREFIX): Likewise. (SCRIPTS): Update generation of Windows batch files accordingly. (scripts-install): Robustify. * install-sh: Update to newer version. * install.bat: Remove. * qm/setup.py (find_packages_r): Fix typo. * qm/fields.py (SetField.FormatValueAsHtml): Do not generate empty tables. (SetField.ParseFormValue): Update accordingly. * qm/web.py (WebRequestHandler.do_GET): Simplify. (WebRequestHandler.do_POST): Likewise. (make_select): Correct HTML generation. * qm/test/.cvsignore: Add qmtest.bat. * qm/test/web/web.py (QMTestServer.HandleSubmitItem): Generate valid URLs for next submission when redisplaying. 2003-07-24 Nathaniel Smith * GNUmakefile.in (RELLIBDIR): Don't add slashes to prefix when matching for removal. Strip slashes after prefix removal. (RELSHAREDIR): Likewise. (RELINCDIR): Likewise. 2003-07-24 Nathaniel Smith * tests/xmldb/common.qms/graph_complete.qmt: Delete. * tests/xmldb/common.qms/graph_cycle.qmt: Likewise. * tests/xmldb/common.qms/graph_pass.qmt: Likewise. 2003-07-24 Mark Mitchell * qm/test/cmdline.py (QMTest.GetVersion): New method. 2003-07-24 Mark Mitchell * version: Update. 2003-07-23 Nathaniel Smith * qm/test/base.py (qm.graph): Don't import. * qm/graph.py: Delete. 2003-07-22 Mark Mitchell * qm/fields.py (Field._GetHtmlFormFieldName): Rename to ... (Field.GetHtmlFormFieldName): ... this. (IntegerField.FormatValueAsHtml): Adjust accordingly. (TextField.FormatValueAsHtml): Likewise. (TupleField.FormatValueAsHtml): Likewise. (SetField.FormatValueAsHtml): Likewise. (SetField.ParseFormValue): Do not validate newly added values. (AttachmentField.FormatValueAsHtml): Adjust use of _GetHtmlFormFieldName. (EnumerationField.FormatValueAsHtml): Likewise. (ChoiceField.FormatValueAsHtml): Always have at least one choice. (ChoiceField.Validate): New method. * qm/test/test.py (Test.arguments): Adjust the test_id field to allow creation from the GUI. * qm/test/web/web.py (QMTestServer.HandleSubmitItem): Simplify. * tests/regress/tuple1: New test. 2003-07-21 Nathaniel Smith * qm/fields.py (TupleField.Validate): Return the computed value. 2003-07-21 Vladimir Prus Mark Mitchell * qm/attachment.py (FileAttachmentStore.GetDataFile): Fix typo. * tests/regress/attachment1/attachment1: New file. * tests/regress/attachment1/results.qmr: Likewise. * tests/regress/attachment1/test.qmt: Likewise. * tests/regress/attachment1/QMTest/.cvsignore: Likewise. * tests/regress/attachment1/QMTest/attachment_test.py: Likewise. * tests/regress/attachment1/QMTest/classes.qmc: Likewise. * tests/regress/attachment1/QMTest/configuration: Likewise. 2003-07-15 Vladimir Prus Mark Mitchell * qm/attachment.py (AttachmentStore.__init__): Remove. (FileAttachmentStore.__init__): New method. (FileAttachmentStore.GetDataFile): Support relative paths. (TemporaryAttachmentStore.__init__): Adjust accordingly. (TemporaryAttachmentStore.GetDataFile): Remove. * qm/test/classes/xml_database.py (XMLDatabase.__init__): Use the database root when creating the attachment store. 2003-07-15 Vladimir Prus * qm/test/web/web.py (DirPage.GetTestResultsForDirectory): Call __IsLabelInDirectory with two parameters. Fix typo. * qm/test/web/web.py (QMTestServer.HandleSaveExpectations): Do not pass 'context' parameter to Result.__init__. * qm/test/web/web.py (StorageResultStream.__init__): Initialize __annotations. 2003-07-14 Nathaniel Smith * qm/test/classes/pickle_result_stream.py (PickleResultReader.GetResult): Don't catch UnpicklingError; it's not necessary with Python 2.2. (PickleResultReader.__init__): Likewise. Also, fix typo (call self._ResetUnpickler, not self._ResetPickler). 2003-07-09 Nathaniel Smith * qm/test/context.py (Context.items): New method. 2003-07-02 Nathaniel Smith * qm/test/base.py (load_results): Rename 'ResultSource' to 'ResultReader' everywhere. (extension_kinds): Rename "result_source" kind to "result_reader". (__extension_bases): Likewise. And same for the imports just above. * qm/test/result_source.py: Rename to... * qm/test/result_reader.py: ...this. Also rename classes, etc. * qm/test/file_result_source.py: Rename to... * qm/test/file_result_reader.py: ...this. Also rename classes, etc. * qm/common.py (format_time_iso): New function. * qm/db.py: New file. * qm/extension.py (get_class_arguments): Support diamond inheritance. * qm/test/classes/pickle_result_source.py: Remove. (PickleResultSource): Move to... * qm/test/classes/pickle_result_stream.py: ...here. (PickleResultSource): Rename to 'PickleResultReader'. Also rewrite for new metadata handling regime. (PickleResultStream): Rewrite for new metadata handling regime. * qm/test/classes/xml_result_source.py: Remove. (XMLResultSource): Move to... * qm/test/classes/xml_result_stream.py: ...here. (XMLResultSource): Rename to 'XMLResultReader', plus associated renames. Update for new metadata handling regime. (XMLResultStream): Update for new metadata handling regime. * qm/test/result_stream.py (ResultStream.WriteAnnotation): New function. (ResultStream.WriteAllAnnotations): New function. (ResultStream.WriteResult): More detail in docstring. * qm/test/classes/classes.qmc: Add SQL result handling classes, rename 'ResultSource' to 'ResultReader'. * qm/test/cmdline.py (QMTest.__ExecuteSummarize): Copy metadata. * qm/test/execution_engine.py: import time. (ExecutionEngine.Run): Create and write metadata. * qm/test/web.py (StorageResultsStream.__init__): Use 'super'. Handle annotations. (StorageResultsStream.GetAnnotations): New method. (StorageResultsStream.WriteAnnotations: New method. (QMTestServer.HandleSubmitResults): Write out annotations. (QMTestServer.HandleSaveResults): Likewise. * scripts/create-test-database.py: New file. * qm/test/classes/sql_result_stream.py: New file. 2003-07-03 Vladimir Prus * qm/attachment.py (AttachmentStore.GetIndex): Remove. * qm/fields.py (SetField.FormatValueAsHtml): Don't use it. * qm/test/clases/xml_database.py (XMLDatabase. __MakeDataFilePath): Fix typos. 2003-07-03 Vladimir Prus * qm/test/web/web.py (ShowItemPage.MakeDeleteScript): Fix typo. 2003-06-27 Nathaniel Smith * qm/test/classes/classes.qmc: Add pickle_result_source.PickleResultSource. 2003-06-24 Nathaniel Smith * qm/test/result_source.py: New file. * qm/test/file_result_source.py: New file. * qm/test/classes/classes.qmc: Add XMLResultSource. * qm/test/base.py (load_results): Take a database argument, return a ResultSource. Use PickleResultSource/XMLResultSource. (load_outcomes): Take a database argument, use new load_results interface. (_result_from_dom): Move to... * qm/test/classes/xml_result_source.py: ...here. New file. * qm/test/classes/pickle_result_source.py: New file. * qm/test/cmdline.py (qm.test.result.Result): import it. (QMTest.__ExecuteSummarize): Rewrite to use new load_results interface. (QMTest.__GetExpectedOutcomes): Pass database to load_outcomes. (QMTest.__FilterTestsToRun): Likewise. * qm/test/web/web.py (QMTestServer.HandleSubmitExpectations): Likewise. (QMTestServer.HandleSubmitResults): Likewise. 2003-06-24 Mark Mitchell * qm/test/cmdline.py (commands_spec): Add support for "qmtest register --help". 2003-06-23 Nathaniel Smith * qm/fields.py: Fix typo in comment. * qm/test/file_result_stream.py (FileResultStream.__doc__): Fix typo. 2003-06-23 Nathaniel Smith * templates/Makefile: It's 2003 now. * templates/xml: Likewise. * templates/py: Likewise. * templates/html: Likewise. * templates/dtml: Likewise. * templates/docbook-chapter: Likewise. * templates/docbook: Likewise. 2003-06-22 Mark Mitchell * qm/attachment.py (Attachment): Move to start of file. (AttachmentStore.Store): Simplify interface. (FileAttachmentStore.__init__): Remove. (FileAttachmentStore.Store): Adjust. (TemporaryAttachmentStore): Derive from FileAttachmentStore. * qm/fields.py (SetField.__init__): Restore backwards-compatible handling of 'title' and 'description' attributes. (AttachmentField.ParseFormValue): Remove broken code. * qm/label.py (Label): Replace 'sep' with '_sep' throughout. (Label.Components): Remove. (Label.ToPath): Remove. * qm/test/database.py (Database.LabelBasename): Remove. (Database.LabelDirname): Remove. (Database.LabelSeparator): Remove. (Database.GetLabelComponents): Simplify. * qm/test/file_database.py (FileDatabase._IsTestFile): Do not use _IsFile. (FileDatabase._IsResourceFile): Likewise. (FileDatabse._IsSuiteFile): Likewise. (FileDatabase._IsFile): Use _IsTestFile, _IsResourceFile, and _IsSuiteFile. (FileDatabase._GetRelativeLabelPath): New method. (ExtensionDatabase._IsTestFile): New method. (ExtensionDatabase._IsResourceFile): New method. (ExtensionDatabase._IsSuiteFile): New method. (ExtensionDatabase._IsFile): Remove. (ExtensionDatabase._GetRelativeLabelPath): New method. * qm/test/classes/file_label.py (FileLabel.sep): Rename to ... (FileLabel._sep): ... this. (FileLabel.Components): Remove. * qm/test/classes/python_label.py (PythonLabel.sep): Rename to ... (PythonLabel._sep): ... this. (PythonLabel.__valid_label_regexp): Adjust accordingly. * qm/test/classes/xml_database.py (XMLDatabase.__init__): Use FileAttachmentStore for the attachment store. (XMLDatabase.__StoreAttachments): Adjust accordingly. (XMLDatabase.__MakeDataFilePath): New method. (XMLDatabase.AttachmentStore): Remove. * qm/test/web/web.py (QMTestPage.FormatId): Avoid use of label separator. (DirPage.__IsLabelInDirectory): New method. (ShowSuitePage.MakeAbsoluteId): Remove. * qm/test/doc/reference.xml: Improve test database documentation. 2003-06-21 Nathaniel Smith * qm/test/classes/pickle_result_stream.py: import qm.fields. (PickleResultStream): New variable _max_pinned_results. New argument protocol_version. (PickleResultStream.__init__): Use protocol_version. Initialize count of processed `Result's. (PickleResultStream.WriteResult): Keep count of processed `Result's, and call `clear_memo' every after every _max_pinned_results. 2003-06-19 Mark Mitchell * qm/fields.py (diagnostic): Do not import it. (label): Likewise. (user): Likewise. (DomNodeError): Remove. (Field.Validate): Update documentation. (IntegerField.GetValueFromDomNode): Raise QMException, not DomNodeError. (TextField.GetValueFromDomNode): Likewise. (SetField.GetValueFromDomNode): Likewise. (AttachmentField.GetValueFromDomNode): Likewise. (EnumerationField.GetValueFromDomNode): Likewise. * qm/test/context.py (Context.__init__): Update documentation string. * qm/test/classes/xml_database.py (XMLDatabase._GetTestFromPath): Handle all exceptions. (XMLDatabase._GetResourceFromPath): Handle all exceptions. * qm/test/doc/manual.xml (context_class): New entity. (result_class): Likewise. * qm/test/doc/reference.xml: Update sections on writing test and resource classes. * qm/fields.py: More massive reorganization and cleanup. * qm/test/doc/manual.xml: Add links to onlin documentation. * qm/test/doc/reference.xml: Describe Field classes. 2003-06-18 Mark Mitchell * README: Correct typo. * qm/test/base.py (load_results): Likewise. * GNUmakefile.in (PYTHON_VERSION): Remove. (PYTHON_PREFIX): Remove. (doc-python): Conditionalize on the avaialability of happydoc. * configure.in (PYTHON_VERSION): Don't AC_SUBST it. (PYTHON_PREFIX): Likewise. * configure: Regenerated. * qm/fields.py: Remove all traces of PropertyDeclaration. * qm/xmlutil.py (load_xml): Update comments. * qm/test/qmtest.py: Try to make sure that gc.collect is called. * qm/test/doc/reference.xml: Correct typos. * qm/test/share/dtml/show.dtml: Use Field.IsHidden. * qm/test/web/web.py (ShowItemPage.FormatFieldValue): Likewise. (QMTestServer.HandleRunTests): Tidy. 2003-06-16 Nathaniel Smith * qm/test/qmtest.py (check_python_version): Call `str' on numbers before joining them. 2003-06-16 Nathaniel Smith * qm/test/qmtest.py: Import sys. (_required_python_version): New variable. (check_python_version): New function. (main): Call it. * qm/setup_path.py.in (__unsupported_python_version): Remove, and remove calls below. * qm/setup_path.py.in (add_to_python_path): Remove, and don't call it. (__doc__): Remove now inaccurate docstring. * qm/setup_path.py.in: Move warnings filtering to... * qm/external/__init__.py: ...here. 2003-06-15 Nathaniel Smith * qm/test/text_result_stream.py: Move into classes/. * qm/test/classes/classes.qmc: Add TextResultStream. * qm/test/cmdline.py: Don't import text_result_stream. (QMTest.__init__): New variable __text_result_stream_class_name. (QMTest.GetTextResultStreamClass): New function. (QMTest.__GetResultStream): Use it. * qm/test/cmdline.py (QMTest.__init__): Remove variable __file_result_stream_class. (QMTest.GetFileResultStreamClass): Don't use it. (QMTest.__init__): Remove unused variable __result_stream_class. * qm/test/cmdline.py (QMTest.__init__): Typo in comment. * qm/test/execution_engine.py (ExecutionEngine.__init__): Remove unused variables self.__test_results, self.__resource_results. (ExecutionEngine._AddResult): Likewise. * qm/test/web/web.py: Remove from __future__ import nested_scopes line. * qm/test/cmdline.py: Likewise. * qm/fields.py: Likewise. * qm/test/classes/file_label.py: Likewise. * qm/test/classes/xml_database.py: Likewise. * qm/test/classes/python_label.py: Likewise. * qm/test/test.py: Likewise. * qm/test/database.py: Likewise. * qm/extension.py (parse_descriptor): Typo in docstring. 2003-06-12 Nathaniel Smith * qm/qm.sh (qm_python_path_dir): New variable. (PYTHONPATH): Use it. 2003-06-10 Ricardo Anguiano * qm/test/doc/reference.xml: Fixed typo. 2003-06-08 Nathaniel Smith * qm/test/base.py (get_extension_directories): Search for builtin extension classes relative to __file__ rather than QM_LIB_DIR. * GNUmakefile.in (PYTHON_PKG_PREFIX): New variable. (RELLIBDIR): Base on PYTHON_PKG_PREFIX, not @libdir@. (RELLIBDIR, RELSHAREDIR, RELINCDIR): Move up in file, so $(SCRIPTS) rule can see RELLIBDIR. (lib-install): Install classes.qmc into PYTHON_PKG_PREFIX. ($(SCRIPTS)): Bake library directory into installed scripts. * qm/qm.sh (qm_rel_libdir): New variable to hold baked-in library directory. Use it. (QM_TRUE_LIBDIR): New exported variable to help qmtest.py find setup_path.py. * qm/test/qmtest.py: Use it. 2003-06-06 Mark Mitchell * qm/fields.py (FieldEditPage.__init__): Add server parameter. (FieldEditPage.MakeDefaultValueControl): Pass it to FormatValueAsHtml. (Field.FormatValueAsText): Adjust call to FormatValueAsHtml. (Field.FormatValueAsHtml): Add server parameter. (Field.GenerateEditWebPage): Likewise. (Field.MakePropertyControls): Likewise. (IntegerField.FormatValueAsHtml): Add server parameter. (TextField.FormatValueAsHtml): Likewise. (TextField.MakePropertyControls): Likewise. (TupleField.FormatValueAsHtml): Likewise. (SetField.FormaatValueAsHtml): Likewise. (SetField.MakePropertyControls): Likewise. (AttachmentField.FormatValueAsHtml): Likewise. (EnumerationField.FormatValueAsHtml): Likewise. (EnumerationField.MakePropertyControls): Likewise. (ChoiceField.FormatValueAsHtml): Likewise. (TimeField.FormatValueAsHtml): Likewise. (UidField): Remove. * qm/web.py (WebRequestHandler.__HandlePageCacheRequest): Use WebServer.GetCachedPage. (WebRequestHandler.__HandleSessionCacheRequest): Likewise. (WebServer.__init__): Create a page cache. (WebServer.MakeButtonForCachedPopup): New method. (WebServer.MakeConfirmationDialog): Likewise. (WebServer.MakePopupDialog): Likewise. (WebServer.CachePage): Likewise. (WebServer.GetCachedPage): Likewise. (WebServer.__GetPathForCachedPage): Likewise. (make_popup_dialog): Remove. (make_confirmation_dialog): Likewise. (make_popup_page): Likewise. (make_button_for_cached_popup): Likewise. (cache_page): Likewise. (_get_path_for_cache_page): Likewise. (get_from_cache): Likewise. (format_user_id): Likewise. (_page_cache_path): Likewise. * qm/test/web/web.py (ShowItemPage.FormatFieldValue): Adjust calls to FormatValueAsHtml. (ShowItemPage.MakeDeleteScript): Use WebServer.MakeConfirmationDialog. (ShowSuitePage.MakeDeleteScript): Likewise. * qm/external/DocumentTemplate/.cvsignore: Likewise. 2003-06-04 Mark Mitchell * qm/test/classes/dejagnu_test.py (DejaGNUTest._ParseTclWords): Recognize that "[]" does not represent command substitution. * zope-dtml/DocumentTemplate/.cvsignore: Remove. * zope-dtml/ExtensionClass/.cvsignore: Remove. 2003-06-03 Mark Mitchell * qm/test/classes/dg_test.py (DGTest.DGException): New class. (DGTest._RunDGTest): Tweak annotation formatting. (DGTest._ExecuteFinalCommand): Use DGException to signal problems, rather than NotImplementedError. 2003-06-02 Mark Mitchell * GNUmakefile.in (INSTALL_DOCUMENTATION): New variable. (doc-install): Guard it by testing INSTALL_DOCUMENTATION. * configure.in (INSTALL_DOCUMENTATION): Set it. * configure: Regenerated. * README: Mention HappyDoc. * qm/test/classes/dejagnu_stream.py (DejaGNUStream.__summary_outcomes): New variable. (DejaGNUStream.Summarize): Use it. * qm/test/classes/dejagnu_test.py (DejaGNUTest._ParseTclWords): Correct variable substitution. * qm/test/classes/dejagnu_stream.py: New file. * qm/test/classes/dejagnu_test.py: New file. * qm/test/classes/dejagnu_base.py: New file. * qm/test/classes/dg_test.py: New file. * qm/test/classes/classes.qmc: Update. 2003-05-13 Mark Mitchell * qm/test/cmdline.py: Import result_stream. (QMTest.summary_formats): Add "batch". (QMTest.__init__): Set __expected_outcomes to None. (QMTest.__ExecuteSummarize): Simplify. (QMTest.__ExecuteRun): Likewise. (QMTest.__ExecuteGUI): Likewise. (QMTest.__FilterTestsToRun): Remove expectations parameter; use __GetExpectedOutcomes. (QMTest.__GetExpectedOutcomes): Cache results. (QMTest.__GetResultStreams): Create the TextResultStream here. * qm/test/execution_engine.py (ExecutionEngine.__init__): Add expectations parameter. (ExecutionEngine.Run): Return a value. (ExecutionEngine._AddResult): Set any_unexpected_outcomes if appropriate. * qm/test/execution_thread.py (ExecutionThread.__init__): Add expectations parameter. * qm/test/result_stream.py (ResultStream.arguments): New variable. * qm/test/text_result_stream.py (TextResultStream): Inherit from FileResultStream. (TextResultStream.__init__): Remove parameters. * qm/test/web/web.py (QMTestServer.HandleRunTests): Update creation of ExecutionThread. * qm/test/doc/reference.xml: Document "batch" output format. * qm/test/doc/tour.xml: Update sample output. 2003-05-09 Mark Mitchell * qm/attachment.py (atexit): Do not import it. (temporary_directory): Import it. (AttachmentStore.all_stores): Remove. (AttachmentStore.__init__): Do not update it. (FileAttachmentStore): Use TemporaryDirectory. (FileAttachmentStore.__CleanUpTemporaryDirectory): Likewise. (is_temporary_location): Use string.startswith. (get_attachment_store): Remove. * qm/common.py (load_class): Support new-style classes. (rmdir_recursively): Remove. (make_temporary_directory): Likewise. (find_program_in_path): Remove. (starts_with): Remove. (ends_with): Likewise. (read_assignments): Use string.startswith. * qm/executable.py (F_GETFD): Do not set it. (F_SETFD): Likewise. (FD_CLOEXEC): Likewise. (Executable.__init__): Remove. (Executable.Run): Use fnctl.F_GETFD, etc. (RedirectedExecutable): Inherit from TimeoutExecutable. Make adjustments accordingly. (Filter): New class. * qm/extension.py (Extension): Make it a new-sytle class. * qm/fields.py (Field.ParseFormValue): Add attachment_store parameter. (Field.FormDecodeValue): Likewise. (UploadAttachmentPage): Do not encode an attachment store. (AttachmentField.FormDecodeValue): Do not decode it either. * qm/platform_unix.py (get_temp_directory): Remove. * qm/temporary_directory.py: New file. * qm/web.py (atexit): Do not import it. (temporary_directory): Import it. (cache_page): Use TemporaryDirectory. * qm/test/base.py (_result_from_dom): Do not use a context when creating 'Result' objects. * qm/test/cmdline.py (QMTest.__ExecuteSummarize): Handle -fnone. * qm/test/context.py (Context): Inherit from types.DictType. (ContextWrapper): Remove. * qm/test/database.py (ItemDescriptor._Execute): Compare context to None, rather than using "if context". * qm/test/execution_engine.py (ExecutionEngine._RunTests): Do not use a context when creating 'Result' objects. * qm/test/file_result_stream (FileResultStream.arguments): Add default value for 'filename' attribute. * qm/test/qmtest.py (main): New method. Collect garbage. * qm/test/result.py (Result.__init__): Remove 'context'. (Result.GetContext): Remove. * qm/test/result_stream.py (ResultStream.kind): Define. * qm/test/target.py (Target.RunTest): Do not use a context when creating 'Result' objects. (Target._FinishResourceSetUp): Add 'properties' parameter. (Target._SetUpResource): Adjust accordingly. (Target._CleanUPResource): Do not use a context when creating 'Result' objects. * qm/test/classes/command.py (ExecTestBase.InputExecutable): Remove. * qm/test/classes/process_target.py (ProcessTarget.RunTest): Do not use a context when creating 'Result' objects. * qm/test/classes/serial_target.py (SerialTarget.__init__): Create a temporary directory. * qm/test/classes/temporary.py (TempDirectoryResource): Reimplement in terms of TemporaryDirectory. * qm/test/classes/thread_target.py (LocalThread.__init__): Create a temporary directory. (LocalThread.GetTemporaryDirectory): New method. (ThreadTarget._FinishResourceSetUp): Adjust call to _FinishResourceSetUp. (ThreadTarget._GetTemporaryDirectory): New method. * qm/test/doc/reference.xml: Fix typo. * qm/test/web/web.py (QMTestServer.__init__): Create a temporary attachment store. 2003-04-23 Mark Mitchell * qm/test/context.py (Context.GetAddedProperties): New method. (ContextWrapper.GetAddedProperties): Recur. * qm/test/target.py (Target._SetUpResource): Handle resources dependent on other resources. * qm/test/file_database.py (ExtensionDatabase._IsFile): Handle empty extensions more gracefully. * qm/test/result.py (Result.SetOutcome): Add cause and annotations parameters. (Result.Fail): Use it. 2003-04-17 Mark Mitchell * qm/executable.py (Executable.Spawn): Close the write end of the exception_pipe here. Call _HandleChild. (Executable.Run): Do not close the write end of the exception_pipe. (Executable._InitializeChild): Fix thinko. (Executable._HandleChild): New method. (RedirectedExecutable._HandleChild): New method. (RedirectedExecutable._DoParent): Do not close pipe ends here. (TimeoutExecutable._DoParent): Rename to ... (TimeoutExecutable._HandleChild): ... this. (TimeoutExecutable.Run): Robustify. (TimeoutRedirectedExecutable._DoParent): Remove. (TimeoutRedirectedExecutable._HandleChild): New method. * qm/test/database.py (TestDescriptor.__init__): Correct error in doc-string. * qm/test/resource.py (Resource.SetUp): Improve doc-string. * qm/test/target.py (Target._SetUpResource): Fix typo in comment. * qm/test/doc/reference.xml: Improve target documentation. 2003-04-15 Nathaniel Smith * qm/setup_path.py.in: Make warnings filtering more fine-grained. 2003-04-15 Nathaniel Smith * qm/test/base.py (get_extension_directories): typo in comment. * qm/test/classes/process_target.py (QMTestExecutable): typo in docstring. 2003-04-15 Nathaniel Smith * zope-dtml/ExtensionClass/: Remove. * qm/external/: New directory. * qm/external/__init__.py: New file. * zope-dtml/DocumentTemplate/: Move to... * qm/external/DocumentTemplate/: ...here. * qm/external/DocumentTemplate/DT_String.py (String._ParseTag): Tweak so it can find modules in the same directory. * qm/external/DocumentTemplate/__init__.py: Tweak to work even if ExtensionClass doesn't exist. * qm/external/local-DocumentTemplate-patch: Record the above two changes to ease future upgrades of DocumentTemplate. * GNUMakefile.in (PYTHONDIRS): Remove mention of zope-dtml/. (PYTHON_PACKAGES): Likewise. * qm/web.py: Import DocumentTemplate from new location. 2003-04-13 Mark Mitchell * NEWS: Remove --result-format item and add --result-stream item. Mention "qmtest create". * qm/extension.py (write_extension_file): New function. (read_extension_file): Likewise. (parse_descriptor): Likewise. * qm/fields.py (PythonField): New class. * qm/test/cmdline.py (QMTest.__extension_kinds_string): New variable. (QMTest.extension_output_option_spec): New spec. (QMTest.result_format_spec): Remove. (QMTest.result_stream_spec): New spec. (QMTest.commands_spec): Add "qmtest create". Remove "--result_format". Add "--result_stream" for "qmtest run" and "qmtest summarize". (QMTest.__version_output): Update copyright date. (QMTest.__init__): Set __file_result_stream_class_name and __file_result_stream_class. (QMTest.GetCommandOption): Add documentation. (QMTest.Execute): Add "qmtest create" support. (QMTest.GetFileResultStreamClass): New method. (QMTest.GetResultStreamClass): Remove. (QMTest.__ExecuteCreate): New method. (QMTest.__ExecuteCreateTdb): Use it. (QMTest.__ExecuteExtensions): Use __CheckExtensionKind. (QMTest.__ExecuteSummarize): Use __GetResultStreams. (QMTest.__ExecuteRun): Likewise. (QMTest.__CheckExtensionKind): New method. (QMTest.__GetResultStreams): Likewise. * qm/test/database.py (create_database): Remove. * qm/test/file_result_stream.py: New file. * qm/test/classes/pickle_result_stream.py (PickleResultStream): Inherit from FileResultStream. * qm/test/classes/xml_database.py (XMLDatabase.WriteTest): Use write_extension_file. (XMLDatabase.WriteResource): Likewise. * qm/test/classes/xml_result_stream.py (XMLResultStream): Inherit from FileResultStream. * qm/test/doc/reference.xml: Document new command-line options. * qm/test/web/web.py (QMTestServer.HandleSaveResults): Use QMTest.GetFileResultStreamClass. (QMTestServer.HandleSaveExpectations): Likewise. * share/diagnostics/common.txt: Add invalid descriptor syntax message. * qm/executable.py: Fix typo in comment. 2003-04-12 Mark Mitchell * qm/executable.py (signal): Import it. (time): Likewise. (Executable): Derive from object. (Executable.Spawn): Deal with multiple inheritance. (Executable._InitializeParent): Likewise. (Executable._InitializeChild): Likewise. (Executable._DoParent): Likewise. (Executable._GetChildPID): New method. (TimeoutExecutable): New class. (TimeoutRedirectedExecutable): Likewise. * NEWS: Mention TimeoutExecutable. * README: Note that Python 2.2 is now required. * qm/setup_path.py.in: Reflect Python 2.2 requirement. * qm/test/classes/command.py (ExecTestBase.arguments): Add timeout field. (ExecTestBase.InputExecutable): Use TimeoutRedirectedExecutable as a base class. (ExecTestBase.InputExecutable.__init__): Adjust accordingly. (ExecTestBase.Run): Likewise. * qm/test/classes/mount_database.py (MountDatabase.GetIds): Fix thinko. * qm/test/classes/process_target.py (ProcessTarget.RunTest): Handle unexpected death of the child process. (ProcessTarget.__ReadResults): Likewise. 2003-04-12 Mark Mitchell * qm/read_thread.py: Remove. * qm/write_thread.py: Likewise. * qm/qm.sh: Remove qmtest-remote handling. 2003-03-28 Mark Mitchell * qm/test/classes/process_target.py (ProcessTarget.__init): Move initialization of children to ... (ProcessTarget.Start): ... here. (ProcessTarget.Stop): Call Target.Stop. 2003-03-27 Mark Mitchell * GNUmakefile.in (.PHONY): Mention more targets. (check): Add check-rsh. (check-rsh): New target. * qm/extension.py (Extension._allow_arg_names_matching_class_vars): New variable. (get_class_arguments): Use it. * qm/test/classes/command.py (ExecTest._allow_arg_names_matching_class_vars): Set it. (ShellScriptTest._allow_arg_names_matching_class_vars): Likewise. * qm/test/classes/rsh_target.py (RSHTarget._allow_arg_names_matching_class_vars): Likewise. (RSHTarget.__init__): Always set "arguments". (RSHTarget._GetInterpreter): Fix thinko. * qm/test/doc/reference.xml: Mention the fact that test classes should not use fields with the same names as class variables in base classes. * NEWS: Mention changes. 2003-03-23 Mark Mitchell * qm/common.py (format_traceback): Tweak formatting of generated structured text. * qm/test/base.py (CouldNotLoadExtensionError): New class. (get_extension_class_from_directory): Use it. * qm/test/cmdline.py (QMTest.__ExecuteRegister): Remove explicit exception-handling code. * qm/test/database.py (TestDescriptor.__init__): Use symbolic constants, not hard-coded string, for prerequisites. (NoSuchItemError): New class. (NoSuchTestError): Inherit from it. (NoSuchSuiteError): Likewise. (NoSuchResourceError): Likewise. (Database.RESOURCE): Tweak spelling. (Database.SUITE): Likewise. (Database.TEST): Likewise. (Database._item_exceptions): Likewise. (Database.GetTest): Raise NoSuchTestError. (Database.GetSuite): Raise NoSuchSuiteError. (Database.GetResource): Raise NoSuchResourceError. (Database.GetItem): Implement in terms of GetTest, GetSuite, and GetResource. (Database.GetClassPaths): Do not raise an exception. * qm/test/file_database.py (GetItem): Remove. * qm/test/test.py (Test.PREREQUISITES_FIELD_ID): New variable. * qm/test/classes/classes.qmc: Register mount_database.MountDatabase. * qm/test/classes/mount_database.py: New file. * qm/test/share/messages/diagnostics.txt (no such resource): Remove. (no such test): Likewise. (no such suite): Likewise. (no such item): New message. * qm/test/web/web.py (QMTestServer.HandleShowItem): Simplify. * tests/QMTest/classes.qmc: Remove selftest.RegTest. * tests/QMTest/configuration: Use MountDatabase. * tests/QMTest/selfdb.py: Remove. * tests/QMTest/selftest.py: Likewise. * tests/regress/QMTest/classes.qmc: New file. * tests/regress/QMTest/configuration: Likewise. * tests/regress/QMTest/regression_database.py: Likewise. * tests/regress/QMTest/selftest.py: Likewise. 2003-03-20 Mark Mitchell * qm/test/database.py (ItemDescriptor.GetResources): Use Runnable.RESOURCE_FIELD_ID. (ResourceDescriptor.__init__): Remove dead code. (Database.kind): Remove. (Database.RESOURCE): New variable. (Database.TEST): Likewise. (Database.SUITE): Likewise. (Database.ITEM_KINDS): Likewise. (Database.GetTest): Use GetItem. (Database.GetTestIds): Use GetIds. (Database.GetSuite): Use GetItem. (Database.GetSuiteIds): Use GetIds. (Database.GetResource): Use GetItem. (Database.GetResourceIds): Use GetIds. (Database.GetItem): New method. (Database.GetIds): Likewise. (Database.ExpandIds): Optimize. * qm/test/file_database.py (FileDatabase.GetTestIds): Remove. (FileDatabase.GetSuiteIds): Likewise. (FileDatabase.GetResourceIds): Likewise. (FileDatabase._IsTestFile): Use _IsFile. (FileDatabase._IsSuiteFile): Likewise. (FileDatabase._IsResourceFile): Likewise. (FileDatabase._IsFile): New method. (FileDatabase.GetIds): New method. (FileDatabase.GetItems): Likewise. * qm/test/result.py: Fix formatting. * qm/test/runnable.py (Runnable.RESOURCE_FIELD_ID): New variable. (Runnable.arguments): Use it. * qm/test/classes/xml_database.py (UnknownTestClassError): Remove. (UnknownResourceClassError): Likewise. 2003-03-06 Mark Mitchell * qm/test/command_thread.py (sys): Import it. (CommandThread.run): Remove use of eval. Make use of trace facilities. (CommandThread._Trace): Use it. * qm/test/target.py (Target.__ResourceSetUpException): New class. (Target.RunTest): Make it exception-safe. (Target.__BeginResourceSetUp): Do not create results here when a test cannot be set up; instead, raise an exception. (Target._SetUpResource0: Make it exception-safe. * qm/test/classes/thread_target.py: Add trace messages throughout. * NEWS: Mention defect correction. 2003-02-27 Mark Mitchell * qm/test/cmdline.py (_make_comma_separated_string): New function. (QMTest.commands_spec): Use it. (QMTest.__ExecuteExtensions): Use base.extension_kinds. (QMTest.__ExecuteRegister): Likewise. * qm/test/cmdline.py (QMTest.commands_spec): Add -O. (QMTest.__ExecuteServer): Pass expectations to QMTestServer.__init__. * qm/test/web.py (QMTestServer.__init__): Add expectations parameter. * qm/test/doc/reference.xml: Add documentation for -O. * NEWS: Mention new -O option. 2003-02-24 Mark Mitchell * scripts/qm-release (build_rpm): Use rpmbuild, rather than rpm, to build an RPM. 2003-02-24 Mark Mitchell * qm/test/share/dtml/navigation-bar.dtml (hide_menu): Tweak for Mozilla 1.0.1 compatibility. 2003-02-17 Mark Mitchell * doc/manual/common-manual.xml: Remove documentation about sendmail configuration option. 2003-01-30 Mark Mitchell * qm/fields.py (Field.class_name): Remove. (Field.MakeDomNode): Adjust accordingly. (IntegerField.class_name): Remove. (TextField.class_name): Likewise. (TupleField.class_name): Likewise. (SetField.class_name): Likewise. (AttachmentField.class_name): Likewise. (EnumerationField.class_name): Likewise. (TimeField.class_name): Likewise. (UidField.class_name): Likewise. (from_dom_node): Remove. * qm/test/database.py (ItemDescriptor.GetResources): New method. (TestDescriptor.GetResources): Remove. * qm/test/runnable.py (Runnable.ResourceField): New class. (Runnable.arguments): Add resources. * qm/test/target.py (Target.RunTest): Use __SetUpResources. (Target._SetUpResource): Likewise. (Target.__SetUpResources): New method. * qm/test/test.py (Test.ResourceField): Remove. (Test.ResourceField): Remove. (Test.arguments): Remove resources field. * qm/test/classes/file.py (SubstitutionField.class_name): Remove. 2003-01-21 Jeffrey D. Oldham * qm/fields.py (AttachmentField): Fix typo in introductory comment. 2003-01-21 Jeffrey D. Oldham * qm/test/target.py (Target._RecordResult): Always record the target which the concurrent execution code assumes exists. 2003-01-21 Jeffrey D. Oldham * qm/test/execution_engine.py (ExecutionEngine._RunTests): Fix documentation mistake. Fix typo in comment. (ExecutionEngine._Trace): Remove extraneous comma in parameter list. 2003-01-03 Mark Mitchell * qm/test/database.py (ItemDescriptor.__init__): Do not set __working_directory. (ItemDescriptor.SetWorkingDirectory): Remove. (ItemDescriptor.GetWorkingDirectory): Likewise. (ItemDescriptor._Execute): Do not change directories. * qm/test/classes/xml_database.py (XMLDatabase.__LoadItem): Do not use SetWorkingDirectory. 2003-01-02 Mark Mitchell * NEWS: Mention --result-format. * qm/test/base.py (extension_kinds): Add result_stream. (__extension_bases): Likewise. * qm/test/cmdline.py (PickleResultStream): Don't import it. (QMTest.result_format_spec): New variable. (QMTest.commands_spec): Use it. (QMTest.__init__): Initialize __result_stream_class. (QMTest.GetResultStreamClass): New method. (QMTest.UnexpectedOutcomesStream.__init__): Adjust call to ResultStream.__init__. (QMTest.__ExecuteRun): Use GetResultStreamClass. * qm/test/pickle_result_stream.py: Remove. * qm/test/result_stream.py (ResultStream): Derive from Extension. * qm/test/text_result_stream.py (TextResultStream.__init__): Adjust call to ResultStream.__init__. * qm/test/xml_result_stream.py: New file. * qm/test/classes/classes.qmc: Add XMLResultStream and PickleResultStream. * qm/test/classes/pickle_result_stream.py: New file. * qm/test/doc/reference.xml: Document --result-format. * qm/test/web/web.py (PickleResultStream): Do not import it. (StorageResultStream.__init__): Adjust call to ResultStream.__init__. (QMTestServer.HandleSaveExpectations): Use QMTest.GetResultStreamClass. (QMTestServer.HandleSaveResults): Likewise. 2002-12-31 Mark Mitchell * doc/manual/common-manual.xml: Document click_menus option. * qm/common.py (RcConfiguration): Derive from ConfigParser. (RcConfiguration.__init__): Load the configuration file. (RcConfiguration.Load): Do not call __Load. (RcConfiguration.Get): Simplify. (RcConfiguration.GetOptions): Likewise. (RcConfiguration.__Load): Remove it. * qm/test/share/dtml/navigation-bar.dtml: Suppose clickable menus. * qm/test/web/web.py (QMTestPage.GenerateStartBody): Likewise. * qm/test/doc/reference.xml: Fix typo. 2002-12-23 Mark Mitchell * qm/extension.py (get_class_arguments): Use the __dict__ of the class, rather than a direct attribute reference, when checking to see if the argument list has already been computed. (get_class_arguments_as_dictionary): Likewise. 2002-12-23 Mark Mitchell * qm/test/test.py (Test.TestField): Fix typo in comment. 2002-12-20 Mark Mitchell * qm/extension.py (get_class_arguments): Allow derived classe arguments to override base class arguments. (get_class_arguments_as_dictionary): Reimplement. * tests/xmldb/QMTest/test_inheritance.py: New file. * tests/xmldb/QMTest/classes.qms: Update. * tests/xmldb/api.qms/test.qms/derived.qmt: New test. 2002-12-18 Mark Mitchell * qm/test/classes/file.py (SubstitutionField): Rework, using TupleField as a base class. (FileContentsTest.Run): Remove exception-handling code. (FileContentsTest.__PerformSubstitutions): Correct. * NEWS: Mention change. 2002-12-18 Vladimir Prus Mark Mitchell * qm/extension.py (parse_dom_element): Add attachment_store parameter. * qm/test/classes/xml_database.py: (XMLDatabase._StoreAttachments): New method (XMLDatabase.WriteTest): Call it. (XMLDatabase.WriteResource): Likewise. (XMLDatabase.__ParseTestDocument): Pass store to parse_dom_element. (AttachmentStore.__init__): Call base class __init__. (AttachmentStore.Store): Correct typo. (AttachmentStore.__MakeDataFilePath): Fix path calculation. 2002-12-18 Mark Mitchell * qm/fields.py (ChoiceField): New class. * qm/test/test.py (Test.ResourceField): Likewise. (Test.TestField): Likewise. (Test.arguments): Use them. 2002-12-17 Mark Mitchell * qm/test/result.py (Result): Update documentation string to more clearly describe annotations. * qm/test/web/web.py (ResultPage.__init__): Do not add a "This Test" link to the run menu for a resource. (ResultPage.MakeRunUrl): Rename to ... (ResultPage.GetRunURL): ... this. (ResultPage.GetResultURL): ... new method. (StorageResultsStream.GetResult): New method. (QMTestServer.HandleShowResults): Use it. * qm/test/share/dtml/result.dtml: Display links to resources, as appropriate. * NEWS: Note that links to results are now available. 2002-12-13 Mark Mitchell * qm/test/web/web.py (NewItemPage.GetClassDescriptions): Use self.class_names to get the list of classes. * NEWS: Note that "File/New Resource" now operates correctly. 2002-12-02 > * qm/test/cmdline.py (QMTest.__ExecuteSummarize): Use binary mode to read and write results files. (QMTest.__GetExpectedOutcomes): Likewise. (QMTest.__FilterTestsToRun): Likewise. 2002-12-01 Mark Mitchell * qm/test/doc/tour.xml: Update for QM 2.0. 2002-12-01 Mark Mitchell * qm/fields.py (SetPopupPage): Remove. (TupleField.GetValueFromDomNode): Fix typo. (TupleField.MakeDomNodeForValue): Likewise. 2002-11-29 Mark Mitchell * qm/web.py (WebRequestHandler.__HandleFileRequest): Open files in binary mode. * qm/test/share/dtml/dir.dtml: Avoid constructs which IE does not like. * qm/test/share/dtml/navigation-bar.dtml: Support IE event model. * qm/test/share/web/images/logo.png: Remove. * qm/test/share/web/images/logo.gif: New file. 2002-11-28 Mark Mitchell * NEWS: Note that Netscape 4 is no longer a supported browser. * doc/manual/common-manual.xml: Likewise. * qm/platform_unix.py (open_in_browser): Default to mozilla. * qm/web.py (DTMLPage.GenerateEndBody): Remove Problems? link. (DTMLPage.MakeMenuItem): Remove. (WebRequestHandler.__HandleScriptRequest): Change shutdown message. * qm/test/share/dtml/dir.dtml: Add logo. * qm/test/share/dtml/navigation-bar.dtml: Rework menu logic. * qm/test/web/web.py (QMTestPage.__init__): Update menu items to use URLs, not JavaScript code. * share/dtml/problems.dtml: Remove second parameter to GenerateEndBody. * share/dtml/user.dtml: Likewise. * share/web/common.js (get_left): New function. (get_right): Likewise. (get_top): Likewise. (get_bottom): Likewise. (is_parent_of): Likewise. * share/web/images/logo.png: New file. * share/web/stylesheets/qm.css: Update style for menus. 2002-11-27 Vladimir Prus * qm/test/web/web.py (ResultPage.__init__): Add "This Test" to run menu. (ResultPage.MakeRunUrl): New method. * qm/test/share/dtml/result.dtml (run_test): New method. 2002-11-25 Mark Mitchell * qm/test/base.py (load_results): Support pickled results files. * qm/test/cmdline.py (xml_result_stream): Don't import it. (pickle_result_stream): Do import it. (QMTest.__ExecuteRun): Use PickleResultStream. * qm/test/pickle_result_stream: New file. * qm/test/web/web.py (xml_result_stream): Don't import it. (pickle_result_stream): Do import it. (QMTestServer.HandleSaveResults): Use PickleResultStream. (QMTestServer.HandleSaveExpectations): Likewise. * share/dtml/exception.dtml: Remove out-of-date language. * qm/test/context.py (ContextException.__init__): Initialize the base class. * qm/test/result.py (ContextException): Import it. (Result.NoteException): Handle ContextExceptions specially. * qm/test/target.py (Target.RunTest): But don't do so here. * qm/test/text_result_stream.py (TextResultStream.WriteResult): Output annotations. (TextResultStream._DisplayAnnotations): New method. 2002-11-22 Mark Mitchell * qm/executable.py (Executable.Spawn): Refine previous patch. * qm/executable.py (Executable.Spawn): Handle relative pathnames in a platform-independent manner. (RedirectedExecutable._DoParent): Fix typo. 2002-11-20 Mark Mitchell * qm/test/database.py (is_database): Check more carefully. * qm/test/text_result_stream.py (TextResultStream._DisplayResult): Show annotations for failing tests even in "brief" mode. * tests/QMTest/selfdb.py (RegressionDatabase.GetTestIds): Use is_database. * tests/QMTest/selftest.py (RegTest.Run): Use
 tags to tidy
	output.

2002-11-19  Mark Mitchell  

	* README: Update installation instructions.

2002-11-15  Mark Mitchell  

	* qm/executable.py (cPickle): Import it.
	(fcntl): Likewise.
	(select): Likewise.
	(F_GETFD): New constant.
	(F_SETFD): Likewise.
	(FD_CLOEXEC): Likewise.
	(Executable.Spawn): Add exception_pipe parameter.  Return the PID
	of the child.
	(Executable.Run): Create the exception_pipe.
	* qm/platform_unix.py (RunProgramError): Remove.
	(ProgramStoppedError): Likewise.
	(ProgramTerminatedBySignalError): Likewise.
	(replace_program): Likewise.
	(run_program): Likewise.
	(run_program_captured): Likewise.
	* qm/test/classes/process_target.py
	(ProcessTarget.QMTestExecutable): New class.
	(ProcessTarget.Start): Use it.
	* tests/QMTest/selftest.py (RegTest.Run): Use Executable.

2002-11-15 Mark Mitchell 

	* qm/executable.py: New file.
	* qm/test/classes/command.py (ExecTestBase.RunProgram): Use
	RedirectedExecutable to encapsulate execution.

	* qm/read_thread.py: New file.
	* qm/write_thread.py: Likewise.
	* qm/test/classes/command.py: Use them.

2002-11-12  Mark Mitchell  

	* NEWS: Mention uniform extension file format.
	* qm/extension.py (parse_dom_element): Extend backwards
	compatibility tricks.
	* qm/test/base.py (_get_db_configuration_path): Remove.
	(is_database): Likewise.
	(load_database): Likewise.
	(create_database): Likewise.
	(count_outcomes): Likewise.
	* qm/test/cmdline.py (QMTest.GetDatabase): Adjust call to
	load_database.
	* qm/test/database.py (get_configuration_file): New function.
	(is_database): Likewise.
	(create_database): Likewise.
	(load_database): Likewise.
	* qm/test/text_result_stream.py (TextResultStream._CountOutcomes):
	New method.
	* qm/test/share/dtds/resource.dtd: Remove.
	* qm/test/share/dtds/target.dtd: Likewise.
	* qm/test/share/dtds/test.dtd: Likewise.
	* qm/test/share/dtds/tdb-configuration.dtd: Likewise.

2002-11-11  Mark Mitchell  

	* NEWS: Mention automatic use of context files.
	* qm/common.py (MapReplacer): Remove.
	(OrderedMap): Likewise.
	(replace_by_map): Likewise.
	(invert_map): Likewise.
	* qm/tetst/cmdline.py (QMTest.MakeContext): Use Context.Read.
	* qm/test/context.py (Context.Read): New method.
	* qm/test/doc/reference.xml: Document automatic use of -C option.

2002-11-06  Mark Mitchell  

	* qm/fields.py (BooleanField): New class.
	* qm/xmlutil.py (ParseError): Remove.
	(load_xml_file): Revise documentation.
	(load_xml): Likewise.
	* qm/test/cmdline.py (__ExecuteSummarize): Handle XML parse errors
	gracefully.
	* qm/test/database.py (Database.arguments): Add modifiable.
	(Database.IsModifiable): New method.
	* qm/test/execution_engine.py (ExecutionEngine._AddResult): Tweak
	handling of resource results.
	* qm/test/file_database.py (FileDatabase._AreLabelsPaths): New
	method.  Use it throughout.
	* qm/test/result.py (Result.RESOURCE_SETUP): New variable.
	(Result.RESOURCE_CLEANUP): Likewise.
	(Result.ACTION): Remove.
	(Result.kinds): Update.
	(Result.NoteException): Use HTML formatting for traceback.
	* qm/test/target.py (Target._RecordResult): Do not record the
	target if it is the local target.
	(Target._SetUpResource): Use RESOURCE_SETUP.
	(Target._CleanUpResource): Use RESOURCE_CLEANUP.
	* qm/test/text_result_stream.py (TextResultStream.WriteResult):
	Tweak handling of resource results.
	(TextResultStream._DisplayResult): Process HTML formatting.
	Adjust calls to _WriteOutcome.
	(TextResultStream._WriteOutcome): Distinguish resource results
	from test results.
	* qm/test/classes/command.py (ExecTestBase.Run): Use HTML
	formatting.
	* qm/test/classes/file_label.py (FileLabel.IsValid): Remove.
	* qm/test/classes/xml_database.py (XMLDatabase._GetTestFromPath):
	Hande XML parse errors gracefully.
	(XMLDatabase._GetResourceFromPath): Likewise.
	* qm/test/share/dtml/result.dtml: Take advantage of HTML
	formatting of annotations.
	* qm/test/web/web.py (QMTestPage.__init__): Do not show editing
	choices if the database is not modifiable.
	* tests/QMTest/.cvsignore: New file.

2002-11-01  Mark Mitchell  

	* qm/test/database.py (Database._LabelToPath): Rename to ...
	(Database.LabelToPath): ... this.
	* qm/test/file_database.py (FileDatabase._GetPathFromLabel):
	Adjust.
	(ExtensionDatabase._GetPathFromLabel): Likewise.
	* qm/test/classes/xml_database.py
	(XMLDatabase.__MakeDataFilePath): Likewise.

2002-10-17  Mark Mitchell  

	* qm/extension.py (make_dom_element): Add element parameter.
	(make_dom_document): New method.
	* qm/test/base.py (dtds): Update.
	* qm/test/database.py: Import Runnable.
	(ItemDescriptor.GetItem): Pass along the test database to the
	newly created item.
	* qm/test/resource.py (Resource): Derive from Runnable.
	(Resource.arguments): Remove.
	* qm/test/result.py: Fix formatting.
	* qm/test/runnable.py (Runnable): New file.
	* qm/test/test.py (Test): Derive from Runnable.
	(Test.arguments): Remove.
	(Test.GetId): Remove.
	* qm/test/classes/command.py (ExecTestBase.GetEnvironment): Be
	careful about what kinds of context variables are propagated into
	the environment.
	* qm/test/classes/file.py (FileContentsTest): Simplify.
	* qm/test/clasess/python.py (ExecTest): Likewise.
	* qm/test/classes/xml_database.py (WriteTest): Just use
	make_dom_document.
	(WriteResource): Likewise.
	* qm/test/doc/reference.xml: Update context documentation.
	* qm/test/web/web.py (QMTestServer): Adjust checking of new test
	names.
	* tests/xmldb/QMTest/.cvsignore: New file.
	* tests/xmldb/QMTest/classes.qmc: Likewise.
	* tests/xmldb/QMTest/test_interface.py: Likewise.
	* tests/xmldb/api.qms/test.qms/test_interface.qmt: Likewise.

2002-10-11  Mark Mitchell  

	* GNUmakefile.in (check-threads): Create the target file on the
	fly.
	(check-processes): Likewise.
	* qm/attachment.py: Use atexit.
	* qm/common.py (add_exit_function): Remove.
	(exit): Likewise.
	(print_message): Likewise.
	(_exit_functions): Likewise.
	(_foreign_exit_functions): Likewise.
	* qm/extension.py (Extension.__init__): Use
	get_class_arguments_as_dictionary.
	(get_class_arguments): Rework.
	(get_class_arguments_as_dictionary): Likewise.
	(get_class_description): New method.
	(get_extension_class_name): Likewise.
	(validate_arguments): Likewise.
	(make_dom_element): Likewise.
	(parse_dom_element): Likewise.
	* qm/fields.py: Substantial revisions.
	(TupleField): New class.
	(SetField): Rework display logic.
	* qm/qm.sh (QM_PATH): Export it.
	* qm/user.py (XmlDatabase.Write): Tidy.
	* qm/web.py (WebServer.Bind): Use atexit.
	* qm/xmlutil.py (write_dom_document): Remove.
	* qm/test/base.py (get_db_configuration_directory): Remove.
	(_get_db_configuration_path): Update.
	(is_database): Likewise.
	(create_database): Likewise.
	(get_extension_directories): Tidy.
	(get_class_description): Remove.
	* qm/test/cmdline.py: Add create-target option.
	(QMTest.GetTargetFileName): New method.
	(QMTest.GetTargetsFromFile): Likewise.
	(QMTest.GetTargets): Use them.
	(QMTest.__ExecuteCreateTarget): New method.
	* qm/test/database.py (TestDescriptor.__init__): Remove
	prerequisites, categories, resources.
	(TestDescriptor.GetCategories): Remove.
	(Database.GetConfigurationDirectory): New method.
	(get_configuration_directory): New function.
	* qm/test/qmtest.py (print_error_message): Simplify.
	Use sys.exit, not qm.exit.
	* qm/test/resource.py (Resource.kind): New class variable.
	* qm/test/target.py (Target.kind): Likewise.
	(Target.RunTest): Provide more information about interrupted
	tests.
	* qm/test/test.py (Test.kind): New class variable.
	(Test.arguments): Mark "id" as computed.  Add prerequisites.  Add
	resources.
	* qm/test/classes/process_target.py: Use integer fields where
	possible.
	* qm/test/classes/rsh_target.py: Fix typo in comment.
	* qm/test/classes/thread_target.py: Use integer fields where
	possible.
	* qm/test/classes/xml_database.py: Use XML processing code from
	the extension module throughout.
	* qm/test/doc/reference.xml: Update.
	* qm/test/share/dtml/show.dtml: Simplify.
	* qm/test/share/dtml/add-category.dtml: Remove.
	* qm/test/share/dtml/add-prerequisite.dtml: Remove.
	* qm/test/share/dtml/add-resource.dtml: Remove.
	* qm/test/share/messages/diagnostics.txt: Update.
	* qm/test/web/web.py (AddPrerequisitePage): Remove.
	(AddResourcePage): Remove.
	(MakePrerequisitesControl): Likewise.
	(MakeResourcesControl): Likewise.
	(HandleAddPrerequisite): Likewise.
	(QMTestServer.SubmitItem): Simplify.
	* tests/QMTest/selfdb.py (QMSelftestDatabase._QualifyTests):
	Adjust.

2002-09-29  Mark Mitchell  

	* README: Fix formatting.
	* qm/common.py (FileSystemMutex): Remove.
	* qm/common.py (open_temporary_file): Raise QMExceptions, not
	other varieties of Exception.
	(make_temporary_directory): Likewise.
	* qm/fields.py (Field.GetProperty): Likewise.
	* qm/platform.py (MailError): Derive from QMException.
	* qm/platform_unix.py (SignalException.__init__): Fix typo.
	(send_email): Raise QMExceptions.
	(run_program): Likewise.
	(run_program_captured): Likewise.
	* qm/web.py: Likewise.
	(AddressInUseError): Derive from QMException.
	(PrivilegedPortError): Likewise.
	(NoSessionError): Likewise.
	(InvalidSessionError): Likewise.
	* qm/test/base.py (create_database): Allow the creation of
	databases in existing directories.
	* qm/test/cmdline.py (qm.test.web.web): Import it.
	(signal): Likewise.
	(QMTest.daemon_option_spec): New class variable.
	(QMTest.pid_file_option_spec): Likewise.
	(QMTest.commands_spec): Add them.
	(QMTest.ExecuteServer): Handle them.
	* qm/test/qmtest.py: Handle SignalExceptions.
	* qm/test/doc/reference.xml: Add documentation for --daemon and
	--pid-file.
	* qm/test/share/messages/diagnostics.txt: Remove db path exists
	message.
	* qm/test/util/README: New file.
	* qm/test/util/svr4_init/red_hat_linux: Likewise.
	* qm/test/web/web.py: Use qm.test.cmdline.QMTest instead of QMTest
	throughout.

2002-08-28  Mark Mitchell  

	* qm/test/execution_engine.py (ExecutionEngine._CheckForResponse):
	Decrement running here.
	(ExecutionEngine._AddResult): Not here.
	(ExecutionEngine._AddUntestedResult): Do not muck with running here.

2002-08-22  Mark Mitchell  

	* GNUmakefile.in (check): Use check-serial, check-threads,
	check-processes.
	(check-serial): New target.
	(check-threads): Likewise.
	(check-processes): Likewise.
	* qm/test/cmdline.py (QMTest.Execute): Return a value.
	(QMTest.GetTargets): Handle errors in the target file more
	gracefully.
	(QMTest.__ExecuteRun): Return a value.
	(QMTest.__ExecuteRemote): Likewise.
	(QMTest.__ExecuteSummarize): Likewise.
	(QMTest.__GetExpectedOutcomes): Always return a valid map.
	* qm/test/qmtest.py: Return a non-zero exit code if there are
	unexpected outcomes.
	* qm/test/resource.py (Resource.arguments): Correct use of hidden
	parameter.
	* qm/test/test.py (Test.arguments): Likewise.
	* qm/test/classes/process_target.py (ProcessTarget.arguments): Fix
	typo in default_value for database_path.
	(ProcessTarget.__init__): Fix
	typo.
	(ProcessTarget.Start): Use "self.processes" not "self.concurrency".
	* qm/test/classes/rsh_target.py (RSHTarget.__init__): Likewise.
	* qm/test/classes/thread_target.py (ThreadTarget.arguments): Fix
	use of default_value.
	(ThreadTarget.__init__): Expect "concurrency" to be a string.
	* qm/test/share/dtml/dir.dtml: Fix grammar in displayed message.
	* qm/test/share/messages/diagnostics.txt: Add message.
	* tests/QMTest/thread_target: New file.
	* tests/QMTest/process_target: New file.

2002-08-08  Zack Weinberg  

	Revised test suite.

	* New files:
	tests/QMTest/classes.qmc
	tests/QMTest/selfdb.py
	tests/QMTest/selftest.py
	tests/regress/cycle1/QMTest/configuration
	tests/regress/cycle1/a.qmt
	tests/regress/cycle1/b.qmt
	tests/regress/cycle1/results.qmr
	tests/regress/cycle2/QMTest/configuration
	tests/regress/cycle2/a.qmt
	tests/regress/cycle2/b.qmt
	tests/regress/cycle2/c.qmt
	tests/regress/cycle2/results.qmr
	tests/regress/cycle3/QMTest/configuration
	tests/regress/cycle3/a.qmt
	tests/regress/cycle3/b.qmt
	tests/regress/cycle3/c.qmt
	tests/regress/cycle3/results.qmr
	tests/regress/cycle4/QMTest/configuration
	tests/regress/cycle4/a.qmt
	tests/regress/cycle4/b.qmt
	tests/regress/cycle4/c.qmt
	tests/regress/cycle4/d.qmt
	tests/regress/cycle4/e.qmt
	tests/regress/cycle4/f.qmt
	tests/regress/cycle4/results.qmr
	tests/regress/cycle5/QMTest/configuration
	tests/regress/cycle5/a.qmt
	tests/regress/cycle5/b.qmt
	tests/regress/cycle5/results.qmr
	tests/regress/gilles1/QMTest/configuration
	tests/regress/gilles1/a.qmt
	tests/regress/gilles1/b.qmt
	tests/regress/gilles1/c.qmt
	tests/regress/gilles1/results.qmr
	tests/regress/noresource/QMTest/configuration
	tests/regress/noresource/results.qmr
	tests/regress/noresource/test.qmt
	tests/regress/noresource/test2.qmt
	tests/regress/xml1/QMTest/configuration
	tests/regress/xml1/asdfasdf.qmt
	tests/regress/xml1/fnord.qmt
	tests/regress/xml1/results.qmr
	tests/xmldb/.cvsignore
	tests/xmldb/QMTest/configuration

	* Renamed files from:
	tests/unit.qms/common.qms/format_time1.qmt
	tests/unit.qms/common.qms/graph_complete.qmt
	tests/unit.qms/common.qms/graph_cycle.qmt
	tests/unit.qms/common.qms/graph_pass.qmt
	tests/unit.qms/common.qms/label_is_valid.qmt
	tests/unit.qms/common.qms/label_thunk.qmt
	tests/unit.qms/common.qms/parse_time1.qmt
	tests/unit.qms/common.qms/parse_time2.qmt
	tests/unit.qms/common.qms/parse_time3.qmt
	tests/unit.qms/common.qms/parse_time4.qmt
	tests/unit.qms/common.qms/parser_create.qmt
	tests/unit.qms/common.qms/parser_dup_command_long.qmt
	tests/unit.qms/common.qms/parser_dup_command_short.qmt
	tests/unit.qms/common.qms/parser_help.qmt
	tests/unit.qms/common.qms/parser_no_long.qmt
	tests/unit.qms/common.qms/parser_parse.qmt
	tests/unit.qms/common.qms/parser_two_char_short.qmt
	tests/unit.qms/test.qms/classes.qms/scripttest1.qmt
	tests/unit.qms/test.qms/classes.qms/tempdir1.qma
	tests/unit.qms/test.qms/classes.qms/tempdir1.qmt

	* to:
	tests/xmldb/common.qms/format_time1.qmt
	tests/xmldb/common.qms/graph_complete.qmt
	tests/xmldb/common.qms/graph_cycle.qmt
	tests/xmldb/common.qms/graph_pass.qmt
	tests/xmldb/common.qms/label_is_valid.qmt
	tests/xmldb/common.qms/label_thunk.qmt
	tests/xmldb/common.qms/parse_time1.qmt
	tests/xmldb/common.qms/parse_time2.qmt
	tests/xmldb/common.qms/parse_time3.qmt
	tests/xmldb/common.qms/parse_time4.qmt
	tests/xmldb/common.qms/parser_create.qmt
	tests/xmldb/common.qms/parser_dup_command_long.qmt
	tests/xmldb/common.qms/parser_dup_command_short.qmt
	tests/xmldb/common.qms/parser_help.qmt
	tests/xmldb/common.qms/parser_no_long.qmt
	tests/xmldb/common.qms/parser_parse.qmt
	tests/xmldb/common.qms/parser_two_char_short.qmt
	tests/xmldb/test.qms/classes.qms/scripttest1.qmt
	tests/xmldb/test.qms/classes.qms/tempdir1.qma
	tests/xmldb/test.qms/classes.qms/tempdir1.qmt

	* Modified files:
	GNUmakefile.in (check): Pass -c qmtest_path= to qmtest run.
	tests/QMTest/configuration: Use QMSelftestDatabase.

	* Deleted files:
	tests/common.qms


2002-08-08  Zack Weinberg  

	* qm/test/target.py: Import NoSuchResourceError from
	qm.test.database.
	(Target._SetUpResource): If GetResource throws NoSuchResourceError,
	note the exception and return.

	* qm/common.py (load_module): If imp.load_module fails,
	remove the broken object from sys.modules.

	* qm/label.py (Label.SplitLeft): New method.
	* qm/test/database.py (Database.SplitLabelLeft): New method.
	* qm/test/result.py (Result.Annotate): New method.
	(Result.Fail): Use it.

2002-08-08  Mark Mitchell  

	* qm/common.py (QMException.__init__): New method.
	(PythonException): New class.
	* qm/test/base.py (get_extension_class_from_directory): Raise
	a PythonException.
	* qm/test/cmdline.py (QMTest.__ExecuteRegister): Handle it.

2002-08-07  Mark Mitchell  

	* qm/test/base.py (load_database): Add documentation.  Adjust call
	to get_extension_class.
	(get_extension_directories): Add database_path parameter.  Search
	the QMTest subdirectory of that directory as well.
	(get_extension_class_names): Add database_path parameter.
	(get_extension_class): Likewise.
	* qm/test/cmdline.py (QMTest.__ExecuteExtensions): Pass it.
	(QMTest.__ExecuteRegister): Likewise.

	* qm/test/execution_engine.py
	(ExecutionEngine._CheckForResponse): Update trace message.  Do
	not block.
	(ExecutionEngine._AddResult): Add consistency check.
	(ExecutionEngine._AddUntestedResult): Mark untested tests as
	running before they are marked as untested.

	* qm/test/base.py (get_extension_directories): Make sure the
	QMTest subdirectory of the database is searched
	* qm/test/datbase.py (Database.GetClassPaths): Do not search it
	here.
	* qm/test/doc/reference.xml: Update description of locations
	searched for test classes.

	* GNUmakefile.in (doc-python): Simplify.

	* qm/fields.py (Field.__init__): Check that properties provided
	make sense for this class.

	* qm/test/execution_engine.py (ExecutionEngine.__init__): Set
	__running.
	(ExecutionEngine.RunTests): Use it to detect deadlock.  Remove
	__debug__ guards over all calls to _Trace.
	(ExecutionEngine._AddResult): Decrement running when a test result
	is seen.
	(ExecutionEngine._Trace): Check __debug__ here.
	* qm/test/classes/thread_target (ThreadTarget.__init__): Correct
	typo.
	* qm/test/share/messages/diagnostics.txt: Move dependency cycle
	message here.
	* share/diagnostics/common.txt: Remove it from here.

	* NEWS: Mention "qmtest extensions" and "qmtest register".
	* qm/common.py (load_module): Separate path parameter into
	search_path and load_path.
	(load_class): Likewise.
	* qm/extension.py: New class.
	* qm/test/base.py (dtds): Mention class-directory.
	(load_database): Handle "xmldb.Database" and
	"qm.test.xmldb.Database" specially for backwards compatibility.
	(get_extension_directories): Do not require a database.
	(get_extension_class_from_directory): New method.
	(get_extension_class): Use it.
	(get_class_arguments): Remove.
	(__extension_bases): New variable.
	* qm/test/cmdline.py (QMTest.extension_kind_option_spec): New variable.
	(commands_spec): Add "extensions", "register", and "help".
	(QMTest.Execute): Support them.
	(QMTest.GetDatabase): Instantiate the database if it does not
	already exist.
	(QMTest.GetTargets): Adjust for changes to Target.
	(QMTest.__ExecuteCreateTdb): Adjust name of default database
	class.
	(QMTest.__ExecuteExtensions): New method.
	(QMTest.__ExecuteRegister): Likewise.
	(QMTest.__WriteCommandHelp): New method.
	* qm/test/database.py: Import qm.extension, qm.fields.
	(ItemDescriptor.GetClassArguments): Use
	qm.extension.get_class_arguments.
	(ItemDescriptor._MakeItem): Remove.
	(Database): Inherit from Extension.
	(Database.arguments): New field.
	(Database.__init__): Adjust accordingly.
	* qm/test/file_database.py: (ExtensionDatabase.__init__): Remove.
	(ExtensionDatabase.arguments): New variable.
	(ExtensionDatabase.GetTestExtension): Adjust.
	(ExtensionDatabase.GetSuiteExtension): Likewise.
	(ExtensionDatabase.GetResourceExtension): Likewise.
	(ExtensionDatabase.GetTestPath): Likewise.
	(ExtensionDatabase._IsTestFile): Likewise.
	(ExtensionDatabase._IsSuiteFile): Likewise.
	(ExtensionDatabase._IsResourceFile): Likewise.
	* qm/test/resource.py (Resource): Inherit from Extension.
	(Resource.__init__): Remove.
	(Resource.arguments): Add "id".
	* qm/test/target.py (Target): Inherit from Extension.
	(Target.__init__): Simplify.
	(Target.attributes): New variable.
	(Target.GetName): Adjust.
	(Target.GetGroup): Likewise.
	(Target.GetProperty): Remove.
	* qm/test/test.py (Test): Inherit from Extension.
	(Test.arguments): Add "id".
	(Test.__init__): Simplify.
	(Test.GetTargetGroup): Adjust.
	* qm/test/xmldb.py: Remove.
	* qm/test/classes/classes.qmc: Add xml_database.XMLDatabase.
	* qm/test/classes/file.py (SubstitutionField.__init__): Simplify.
	(FileContentsTest.arguments): Fix typos.
	(FileContentsTest.__init__): Adjust.
	* qm/test/classes/process_target.py (ProcessTarget.__init__):
	Simplify.
	(ProcessTarget.arguments): New variable.
	(ProcessTarget.Start): Adjust.
	* qm/test/classes/python.py (ExecTest.__init__): Adjust.
	(BaseExceptionTest.__init__): Likewise.
	(ExceptionTest.__init__): Likewise.
	(StringExceptionTest.arguments): Fix typo.
	* qm/test/clases/rsh_target.py (RSHTarget.arguments): New variable.
	(RSHTarget.GetInterpreter): Adjust.
	* qm/test/classes/serial_target.py: Adjust class description.
	* qm/test/classes/thread_target.py (ThreadTarget.__init__):
	Adjust.
	(ThreadTarget.arguments): New variable.
	(ThreadTarget.start): Adjust.
	* qm/test/classes/xml_database.py: New file.
	* qm/test/doc/reference.xml: Update to mention new command-line
	options.
	* qm/test/share/dtml/dir.dtml: Correct grammar in displayed pages.
	* qm/test/share/messages/diagnostics.txt: Add more messages.
	* qm/test/web/web.py (ShowSuitePage.__init__): Fix typo.
	(QMTestServer.HandleSubmitItem): Adjust call to get_class_arguments.
	* share/diagnostics/common.txt: New messages.

2002-07-31  Mark Mitchell  

	* NEWS: Discuss requirement that classes be listed in classes.qmc.
	* qm/test/share/doc/reference.xml: Update description of extension
	classes.

2002-07-24  Mark Mitchell  

	* NEWS: Mention ProcessTarget.
	* qm/qm.sh (QM_BUILD): Do not override an existing value.
	* qm/test/cmdline.py (QMTest.GetTargets): Adjust handling of
	concurrency values.
	(QMTest.__ExecuteRemote): Likewise.
	* qm/test/execution_engine.py (ExecutionEngine.AddInputHandler):
	New method.
	(ExecutionEngine._CheckForResponse): Dispatch to input handlers if
	appropriate.
	* qm/test/target.py (Target.__init__): Remove concurrency
	parameter.
	(Target.GetConcurrency): Likewise.
	* qm/test/classes/classes.qmc: Add ProcessTarget..
	* qm/test/classes/process_taret.py: New file.
	* qm/test/classes/rsh_target.py: Build atop ProcessTarget
	* qm/test/doc/reference.xml: Describe ProcessTarget.
	* qm/test/share/dtds/target.dtd: Remove concurrency field.

2002-07-23  Mark Mitchell  

	* GNUmakefile.in (lib-install): Improve portability.

2002-07-09  Mark Mitchell  

	* qm/test/classes/thread_target.py: Remove tabs.
	* qm/common.py (lock): Import it.
	(__load_module_lock): New variable.
	(load_module): Use it to enforce thread safety when loading
	modules.
	* qm/lock.py: New file.
	* qm/test/execution_engine.py (ExecutionEngine.__init__): Do not
	initialize busy_targets.
	(ExecutionEngine.Run): Add additional trace output.
	(ExecutionEngine._RunTests): Do not use busy_targets.  Use the
	length of idle_targets to detect deadlock.

2002-07-04  Mark Mitchell  

	* NEWS: Mention qmtest run --rerun.
	* qm/test/base.py (get_class_arguments): Remove Python 1.5.2
	compatibility code.
	* qm/test/cmdline.py (QMTest.rerun_option_spec): New class
	variable.
	(QMTest.commands_spec): Use it.
	(QMTest.__ExecuteSummarize): Use __GetExpectedOutcomes.
	(QMTest.__ExecuteRun): Likewise.  Use __FilterTestsToRun.
	(QMTest.__GetExpectedOutcomes): New method.
	(QMTest.__FilterTestsToRun): Likewise.

2002-06-30  Mark Mitchell  

	* qm/test/file_database.py (FileDatabase.GetTestPath): Fix typo.
	(FileDatabase._GetLabelFromBasename): New method.
	(FileDatabase._GetLabels): Use it.
	(ExtensionDatabase._GetLabelFromBasename): New method.

2002-06-28  Mark Mitchell  

	* qm/test/file_database.py (FileDatabase.GetRoot): New method.
	(FileDatabase._GetPathFromLabel): Use it.
	(ExtensionDatabase.GetSuitePath): Likewise.
	(ExtensionDatabase._IsSuiteFile): Likewise.
	(ExtensionDatabase._GetPathFromLabel): Likewise.

	* qm/test/file_database.py (ExtensionDatabase): New class, split
	out from ...
	(FileDatabase): ... here.
	* qm/test/xmldb.py (Database): Use 'ExtensionDatabase' as the
	immediate base class.
	(Database.__init__): Adjust accordingly.

	* qm/common.py (timegm): Remove.

2002-06-24  Zack Weinberg  

	* share/diagnostics/common.txt: Add entry for "dependency cycle".
	* qm/test/execution_engine.py (class ExecutionEngine): Implement
	dependency-cycle detection.

2002-06-21  Zack Weinberg  

	* qm/platform_unix.py: Use URL quoting convention (%xx) to escape
	single quotes.

2002-06-19  Zack Weinberg  

	* qm/xmlutil.py: Use xml.dom.minidom.getDOMImplementation() so
	that writexml() will work when xmlplus is installed.

2002-06-17  Mark Mitchell  

	* qm/common.py (sequence_difference): Remove.
	(make_map_from_list): Likewise.
	(purge_keys): Likewise.
	* qm/test/file_database.py (FileDatabase._GetLabels): Use
	JoinLabels, not qm.label.join.
	* qm/test/share/dir.dtml: Remove insertion of "." before test name.

2002-06-13  Mark Mitchell  

	* qm/common.py (MethodShouldBeOverriddenError): Remove.
	* qm/test/qmtest.py: Handle NotImplementedError specially.
	* qm/test/share/messages/diagnostics.txt (not implemented): New
	error message.
	* qm/attachment.py: Use NotImplementedError, not
	MethodShouldBeOverriddenError.
	* qm/fields.py: Likewise.
	* qm/user.py: Likewise.
	* qm/test/command_thread.py: Likewise.
	* qm/test/database.py: Likewise.
	* qm/test/file_database.py: Likewise.
	* qm/test/resource.py: Likewise.
	* qm/test/result_stream.py: Likewise.
	* qm/test/target.py: Likewise.
	* qm/test/test.py: Likewise.

	* NEWS: Mention --version option.
	* qm/test/doc/reference.xml: Add --version description.
	* GNUmakefile.in: Fix typo in comment.
	* qm/cmdline.py (CommandParser.__init__): Do not raise exceptions
	on invalid input.
	* qm/common.py (program_name): Initialize it to 'None'.
	* qm/setup_path.py.in (major_version): New variable.
	(minor_version): Likewise.
	(release_version): Likewise.
	* qm/test/cmdline.py (QMTest.version_option_spec): New variable.
	(QMTest.global_options_spec): Add it.
	(QMTest.__version_output): New variable.
	(QMTest.__init__): Add version number parameters.
	(QMTest.__Execute): Handle --version.
	(QMTest._GetVersionString): New method.
	* qm/test/qmtest.py: Remove duplicate import.  Reorder exception
	handling clauses.

	* NEWS: Mention that --random is no longer the default.
	* qm/test/doc/reference.xml: Update accordingly.

	* qm/common.py (shuffle): Remove.
	* qm/test/cmdline.py (whrandom): Do not import.
	(random): Import.
	(QMTest.random_option_spec): New option.
	(QMTest.commands_spec): Use it.
	(QMTest.__ExecuteRun): Only randomize test order if --random is
	present.
	* qm/test/execution_engine.py (ExecutionEngine._RunTests):
	Preserve the order that tests were presented in the test queues.

	* qm/fields.py (Field.__init__): Remove check for valid labels.
	* qm/label.py: Rework completely so that Label is an abstract
	base class.
	* qm/platform_win32.py (default_shell): Correct spelling of
	COMSPEC environment variable.
	* qm/user.py (Group.__init__): Remove check for valid labels.
	* qm/xmlutil.py (load_xml): Remove incorrect comment.
	* qm/test/base.py (validate_id): Remove.
	(load_database): Convert Unicode strings to ordinary strings
	for use as keyword arguments.
	(extension_kinds): Add label.
	* qm/test/cmdline.py (QMTest.__ExecuteRun): Use the empty string,
	not ".", to indicate that all tests should be run.
	* qm/test/database.py: Rework to provide label manipulation
	functions in terms of a particular label class.
	* qm/test/file_database.py: Likewise.
	* qm/test/xmldb.py (Database): Likewise.
	* qm/test/classes/classes.qmc: Add FileLabel and PythonLabel.
	* qm/test/classes/file_label.py: New file.
	* qm/test/classes/python_label.py: Likewise.
	* qm/test/share/dtds/class-directory.dtd: Add labels.
	* qm/test/web/web.py: Adjust manipulation of labels throughout.
	(QMTestPage.GetDatabase): New method.
	(QMTestPage.FormatId): New method.
	* tests/unit.qms/common.qms/label_is_valid.qmt: Update.
	* tests/unit.qms/common.qms/label_thunk.qmt: Likewise.

2002-06-12  Mark Mitchell  

	* qm/test/execution_engine.py (ExecutionEngine._CheckForResponse):
	Use _UpdateDependentTests.
	(ExecutionEngine._UpdateDependentTests): New method.

2002-06-09  Zack Weinberg  

	* qm/track: Remove .cvsignore files.
	* configure.in: No need to configure gadfly.
	* configure: Regenerate.

2002-05-28  Mark Mitchell  

	* share/web/images/left-arrow.gif: Merge from release-1-1-branch.

	* GNUMakefile.in (PYTHON_PACKAGES): Remove PyXML and xmlrpc.
	* README: Update licensing information about zope-dtml.
	* qm/fields.py (SetField.GetValueFromDomNode): Be tolerant of
	TEXT_NODEs mixed in with the contained elements.
	* qm/qm.sh (QM_PYTHON_FLAGS): Only use -O when running installed
	code; do not use optimization when running from the build tree.
	* qm/trace.py (Tracer.Write): Tweak output format.
	* qm/web.py (xmlrpclib): Do not import it.  Remove XML-RPC
	handling throughout.
	* qm/xmlutil.py: Remove uses of PyXML throughout.
	* qm/test/base.py: Do not default to xmldb for databases that
	have no configuration file.
	(load_results): Do not pass a validate parameter to load_xml.
	* qm/test/database.py (Database.ExpandIds): Tidy.
	* qm/test/execution_engine.py (ExecutionEngine._RunTests): If
	loading a test fails, put the exception traceback in the result.
	* qm/test/xml_result_stream.py (XMLResultStream.WriteResult):
	Use only methods available in DOM, not PyXML extensions.
	* qm/test/xmldb.py (Database.__ParseTestDocument): Add trace
	output.
	(Database.__ParseResourceDocument): Likewise.
	(Database.__GetArgumentsFromDomNode): Likewise.  Be tolerant of
	embedded TEXT_NODEs.
	(Database._Trace): New method.

2002-05-27  Mark Mitchell  

	* qm/track: Remove directory.
	* GNUmakefile.in (QM_TOOLS): Remove QMTrack.

 	Merge from release-1-1-branch.

2002-05-20  Mark Mitchell  

	* qm/common.py (load_module): Insert the path appropriate for the
	loaded module in front of the default directories, rather than
	behind them.
	* NEWS: Update it.

2002-05-15  Mark Mitchell  

	* scripts/qm-release (upload): Update Windows logic.

2002-05-14  Mark Mitchell  

	* scripts/qm-release (tag_qm): Return to the top level directory.

	* qm/test/execution_engine.py (ExecutionEngine._RunTests): Correct
	punctuation in error message.
	* scripts/qm-release (upload): Upload manuals, too.
	(build_exec): Use Python 2.2.
	(build_binary): Use zcat.

	* scripts/qm-release: Set the umask before building distributions.

	* scripts/qm-release (upload): New function.
	* config.guess: New file.

	* scripts/qm-release (TAG): Initialize it.

	* configure.in: Use version to get the version number.
	* configure: Regenerated.

	* scripts/qm-release (tag_qm): Overwrite version, rather than
	appending to it.

	* scripts/qm-release (tag_qm): New function.

	* version: New file.

2002-05-12  Mark Mitchell  

	* qm/test/web/web.py (ShowSuitePage.__init__): Add is_new_suite
	parameter.
	(QMTestServer.HandleCreateSuite): Pass it.
	(QMTestServer.HandleShowSuite): Likewise.
	* qm/test/share/dtml/suite.dtml: Make cancellation of new suite
	requests redirect to the main directory page.

2002-05-01  Mark Mitchell  

	* qm/test/classes/file.py (FileContentsTest.fields): Rename to ...
	(FileContentsTest.arguments): ... this.

2002-04-30  Mark Mitchell  

	* qm/cmdline.py (CommandParser.ParseCommandLine): Avoid joining
	and splitting command-line arguments.

2002-04-15  Mark Mitchell  

	* configure.in: Compute PYTHON_MAJOR and PYTHON_MINOR without
	using here documents inside command substitution.
	* configure: Regenerated.

2002-03-13  Mark Mitchell  

	* scripts/qm-release (build_rpm): Use sudo.
	(TAR_OPTS): Use "root" rather than "0" in owner options.

	* qm/test/cmdline.py (QMTest.MakeContext): Fix typo.
	* NEWS: Note fix.

2002-03-10  Mark Mitchell  

	* qm/common.py (string_types): New variable.

	* qm/test/context.py: Permit Unicode strings throughout.
	* qm/test/result.py: Likewise.

2002-03-10  Mark Mitchell  

	* qm/test/doc/tour.xml: Update tutorial instructions to reflect
	changes in QMTest 1.1.2.
	* qm/test/share/dtml/set-expectations.dtml: Clarify form.

	* configure.in (PYTHON_MAJOR): Robustify checks.
	(PYTHON_MINOR): Likewise.
	* configure: Regenerated.
	* qm/web.py (DocumentTemplate): Guard import with try-block to
	improve error messages.

2002-03-09  Mark Mitchell  

	* qm/test/share/dtml/results.dtml: Simplify.
	* qm/test/web/web.py (StorageResultsStream.__init__): Initialize
	__test_results_in_order.
	(StorageResultsStream.WriteResult): Update it.
	(StorageResultsStream.Start): Likewise.
	(StorageResultsStream.GetTestResultsInOrder): New method.
	(TestResultsPage.__init__): Use it.
	(TestResultsPage.GetTotalUnexpected): Take advantage of the fact
	that test_results is now a list, not a dictionary.
	(TestResultsPage.GetResultsWithOutcome): Likewise.
	(TestResultsPage.GetTestIds): Remove.

	* qm/test/web/web.py (StorageResultsStream.Start): Add test_ids
	parameter; remove existing results for tests that are going to be
	re-run.

	* qm/common.py (starts_with): Simplify.
	(ends_with): Likewise.
	(parse_assignment): New function.
	(read_assignments): Likewise.
	* qm/test/cmdline.py (context_file_name): New member.
	(QMTest.MakeContext): Use read_assignments.
	(QMTest.__ParseContextAssignment): Remove.
	(QMTest.__ParseKeywordArgument): Likewise.
	(QMTest.__ExecuteCreateTdb): Use parse_assignment.
	* qm/test/qmtest.py: Tidy interrupted message.
	* qm/test/share/dtml/load-expected-results.dtml: Remove.
	* qm/test/share/dtml/load-results.dtml: Likewise.
	* qm/test/share/dtml/load.dtml: New file.
	* qm/test/share/dtml/navigation-bar.dtml (load_context): New
	function.
	* qm/test/share/dtml/set-expectation.dtml: New file.
	* qm/test/web/web.py (QMTestPage.__init__): Add load context and
	save context functions to the file menu.
	(LoadExpectedResultsPage): Reimplement using load.dtml.
	(LoadResultsPage): Likewise.
	(LoadContxtPage): Likewise.
	(QMTestServer.__init__): Register context load and save URLs.
	(QMTestServer.HandleClearResults): Summarize the new results
	stream.
	(QMTestServer.HandleLoadContext): New method.
	(QMTestServer.HandleSaveContext): Likewise.
	(QMTestServer.HandleSubmitContext): Likewise.
	(QMTestServer._ClosePopupAndRedirect): New method.

	* COPYING: Replace with the GPL.
	Replace all other copyright notices with references to COPYING.
	* README: Note license change.

2002-03-06  Mark Mitchell  

	* GNUMakefile.in (PYTHON_PACKAGES): Remove sgmlop.
	* qm/attachment.py (AttachmentStore.HandleDownloadRequest): Update
	documentation.
	(AttachmentStore.Store): New method.
	(FileAttachmentStore.Store): Likewise.
	(TemporaryAttachmentStore.Add): Rename to ...
	(TemporaryAttachmentStore.Store): ... this.
	* qm/common.py (QMException): New class.
	(MethodShouldBeOverridenError): Derive from it.
	(MutexError): Likewise.
	(MutexLockError): Likewise.
	(ConfigurationError): Likewise.
	(UserError): Likewise.
	(load_class): Raise QMException, not ValueError.
	(make_temporary_directory): Remove FIXME.
	* qm/fields.py (SetField.FormatValueAsHtml): Tidy.
	(AttachmentField.FormatValueAsHtml): Likewise.
	(EnumerationField.MakePropertyControls): Likewise.
	* qm/platform_unix.py (RunProgramError): Derived from QMException.
	(SignalException): Likewise.
	* qm/web.py (qm_bug_system_url): Use the mailing list address.
	(WebServer.__init__): Register self._HandleProblems, not
	_handle_problems.
	(WebServer._HandleProblems): New method.
	(make_set_control): Remove counter manipulations.
	(make_button_for_popup): Don't cache it.
	(make_button_for_cached_popup): New function.
	(_handle_problems): Remove.
	* qm/xmultil.py (xml.dom.minidom): Import it.
	(load_xml): Use it.
	* qm/test/base.py (valid_id): Raise QMException, not RuntimeError.
	(load_database): Raise QMException, not ValueError.  Allow
	attributes to be passed to the database.
	(create_database): Allow attributes to be stored in the database
	configuration file.
	(get_extension_class): Turn ImportError into QMException.
	(load_results): Do not validate the incoming results file.
	* qm/test/cmdline.py (QMTest.attribute_option_spec): New member.
	(QMTest.Execute): Simplify exception-handling.
	(QMTest.__ParseContextAssignment): Break out ...
	(QMTest.__ParseKeywordArgument): ... this method.
	* qm/test/context.py (ContextException): New class.
	(Context.__getitem__): Raise it instead of KeyError.
	* qm/test/database.py (DatabaseError): Derived from QMException.
	(__init__): Do not require an attachment store.
	(Database.GetAttachmentStore): Require that it be overridden.
	* qm/test/file_database.py (FileDatabase.__init__): Remove the
	store parameter.
	* qm/test/qmtest.py (print_errror_message): Indent the message.
	* qm/test/result.py (Result.outcomes): Order from most
	interesting to least interesting.
	* qm/test/target.py (Target.RunTest): Catch ContextException and
	introduce appropriate failure notices.
	* qm/test/test.py (Test.GetId): New method.
	* qm/test/text_result_stream.py (TextResultStream.Summarize): Tidy
	output.
	* qm/test/xmldb.py (Database.__init__): Do not pass down the
	attachment store.
	(Database.GetAttachmentStore): New method.
	* qm/test/classes/command.py (ExecTestBase): Robustify.
	* qm/test/share/dtds/tdb-configuration.dtd: Allow database
	attributes.
	* qm/test/share/dtml/dir.dtml: Rework display.
	* qm/test/share/dtml/navigation-bar.dtml: Simplify.
	* qm/test/share/dtml/result.dtml: Likewise.
	* qm/test/share/dtml/results.dtml: Rework display.
	* qm/test/share/messages/diagnostics.txt (invalid context
	assignment): Remove.
	(invalid keyword assignment): Add.
	(extension class not found): Likewise.
	* qm/test/web/web.py: Rework substantially.
	* scripts/.cvsignore: New file.
	* share/dtml/problems.dtml: Rework to mention mailing list.
	* share/web/common.js (property_add_or_change): Do not
	restrict to valid labels.
	* share/web/images/left-arrow.gif: New file.
	* share/web/stylesheets/qm.css: Update and extend.
	* qm/test/doc/reference.xml: Document -a option to create-tdb.

2002-02-15  Mark Mitchell  

	* qm/web.py (WebServer.Run): Remove exception-handling code.
	* qm/test/cmdline.py (QMTest.expectations_file_name): New
	variable.
	(QMTest.results_file_name): Likewise.
	* qm/test/share/dtml/load-expected-results.dtml: Use it.
	* qm/test/share/dtml/load-results.dtml: Likewise.
	* qm/test/share/dtml/navigation-bar.dtml (handle_menu_select):
	Reset menus after use.
	* qm/test/web/web.py (QMTestPage.__init__): Use
	QMTest.expectations_file_name and QMTest.results_file_name.  Store
	the global QMTest object for DTML pages.
	(QMTestServer.__init__): Use QMTest.expectations_file_name and
	QMTest.results_file_name.

2002-02-13  Mark Mitchell  

	* qm/test/classes/command.py (Command.ExecTestBase.RunProgram):
	Make sure that result annotations are stored as strings, not
	integers.

	* qm.spec.in (Release): Increment.

2002-02-13  Vladimir Prus 

	* qm/test/web.py (ShowSuitePage.__init__): Fix typo.
	* qm/test/file_database.py (FileDatabase._GetLabels): Likewise.

2002-01-29  Mark Mitchell  

	* qm/test/result.py (Result.MakeDomNode): Fix typo.
	* qm/test/classes/temporary.py (TempDirectoryResource.__init__):
	Remove.
	(TempDirectoryResource.SetUp): Fix typo.
	(TempDirectoryResource.CleanUp): Likewise.

	* qm/test/database.py (ItemDescriptor._MakeItem): Tell a newly
	created test or resource what its name is.

	* qm/xmlutil.py (discard_node): Remove.
	* qm/test/xml_result_stream.py (XMLResultStream.WriteResult):
	Do not use it.
	* qm/test/qmtest.py: Remove Python 1.5 work-around.
	* qm/test/result.py: Alphabetize annotations in results file.

	* qm/test/cmdline.py (QMTest.MakeContext): Fix spelling of
	context file option.

2002-01-27  Mark Mitchell  

	* README (REQUIREMENTS): Note that Python 2.1 or higher
	is required.
	* README.sources: Remove restriction that software must work with
	Python 1.5.
	* configure.in: Check for Python 2.1 or higher.
	* configure: Regenerated.
	* qm/qm.sh (QM_PYTHON_FLAGS): New variable.
	(qm_python): Check /usr/bin/python2 before falling back to
	the python in the PATH.
	* qm/queue.py: Fix copyright notice.
	* qm/setup_path.py.in: Issue an error if an old version of
	Python is in use.
	* qm/trace.py: New file.
	* qm/test/cmdline.py (QMTest.__init__): Create a trace object.
	(QMTest.GetTracer): Return it.
	* qm/test/commnd_thread.py: Fix copyright notice.
	* qm/test/execution_engine.py: Likewise.
	(ExecutionEngine): Add trace message throughout.
	(ExecutionEngine._Trace): New method.
	* qm/test/target.py (Target.RunTest): Remove unnecessary code.
	* qm/test/doc/reference.xml: Update description of how QMTest
	locates the python interpreter to use.

2002-01-23  Mark Mitchell  

	* GNUmakefile.in (INSTALL_DIR): Set the mode of the installed
	directory.

2002-01-17  Mark Mitchell  

	* configure.in: Issue an error if distutils is not installed.
	* configure: Regenerated.
	* qm/test/doc/tour.xml: Update output display.

	* GNUmakefile.in (SCRIPTS): Add $(SCRIPT_EXT).

2002-01-16  Mark Mitchell  

	* qm/structured_text.py: Substantial changes to support a verbatim
	markup.
	* qm/test/result.py (Result.AsStructuredText): Remove.
	* qm/test/text_result_stream.py (TextResultStream._DisplayResult):
	Do not use it.
	* qm/test/classes/command.py (ExecTestBase): Change name of
	"Expected Standard Error" field to "Standard Error".
	(ExecTestBase.RunProgram): Use verbatim formatting for output
	and standard error annotations.
	* qm/test/doc/tour.xml: Update accordingly.
	* qm/test/share/dtml/result.dtml: Adjust formatting.
	* qm/test/web/web.py (TestResultsPage.FormatResult): Remove.
	(QMTestServer.HandleSaveResults): Fix typos.

2002-01-15  Mark Mitchell  

	* qm/test/xmldb.py (Database.WriteSuite): Fix typo.
	* qm/test/classes/command.py (_make_result_for_exception): Remove.
	(ExecTestBase.RunProgram): Use execvpe, not execve.
	* qm/test/web/web.py (qm.test.suite): Import it.
	(QMTestServer.HandleCreateSuite): Pass the server, not the
	test database, to ShowSuitePage.
	(QMTestServer.HandleShowSuite): Likewise.
	(QMTestServer.HandleSubmitSuite): Use Suite, not qm.test.base.Suite.

	* qm.spec.in (Release): Reset to zero.

	* scripts/qm-release (build_source): Change destination for
	PDF manual.

	* configure.in (QM_MINOR_VER): Increment.
	* configure: Regenerated.

	* scripts/qm-release (build_source): Correct copying of PDF
	documentation.

	* scripts/qm-release (build_source): Correct documentation
	building.

	* GNUmakefile.in (lib-install): Correct installation location
	of classes.qmc.
	* qm/web.py (WebServer.handle_error): New method.

2002-01-07  Mark Mitchell  

	* configure.in: Do not build gadfly if it does not exist.

	* scripts/qm-release (build_source): Remove QMTrack from
	the release tarball.

	* NEWS: New file.

	* qm/queue.py: New file.
	* qm/test/base.py (get_extension_class_names_in_directory): Remove
	debugging statement.
	* qm/test/cmdline.py (web.web): Do not import it unconditionally.
	(QMTest.__ExecuteServer): Import it here.
	* qm/test/execution_engine.py (Queue): Do not import it.
	(qm.queue): Import it.
	(ExecutionEngine.__init__): Use qm.queue.Queue, not Queue.Queue.
	(ExecutionEngine.__CheckForResponse): Use qm.queue.Empty, not
	Queue.Empty.

	* qm/test/execution_engine.py (ExecutionEngine.Run): Pass
	self to Target.Start.
	(ExecutionEngine._RunTests): Do not add untested results for
	tests that were not run if immediate termination was requested.
	(ExecutionEngine._AddResult): Do not assume that Result.TARGET
	will be present for all results.
	* qm/test/target.py (Target.Start): Add engine parameter.
	(Target.RunTest): Handle KeyboardInterrupts by stopping the
	execution engine.
	(Target._SetUpResource): Likewise.
	* qm/test/classes/rsh_target.py (RSHTarget.Start): Add engine
	parameter.
	* qm/test/classes/rsh_target.py (ThreadTarget.Start): Likewise.

	* qm/label.py (__label_regex): Add hyphens.
	(__label_regex_with_sep): Likewise.
	* qm/xmlutil.py (discard_node): Implement with
	xml.dom.ext.ReleaseNode.
	* qm/test/context.py (Context.ValidateKey): Allow hyphens.
	* qm/test/execution_engine.py (ExecutionEngine._RunTests): Keep
	the list of idle targets up to date.
	(ExecutionEngine._AddResult): Likewise.
	* qm/test/text_result_stream.py (TextResultStream._DisplayResult):
	Use XPASS and XFAIL where possible.
	(TextResultStream._WriteOutcome): New method.
	* qm/test/classes/ThreadTarget.py (TestResultStream.RunTest): Add
	assertions.
	* qm/test/share/messages/diagnostics.txt: Update documentation
	about labels.
	* qm/test/share/messages/help.txt: Likewise.
	* qm/track/share/messages/diagnostics.txt: Likewise.
	* qm/track/share/messages/help.txt: Likewise.
	* qm/test/doc/reference.xml: Likewise.
	* share/xml/.cvsignore: Add *.dtd.
	* configure.in (AC_PROG_MAKE_SET): Remove.

	* qm/test/share/dtds/result.dtd: Correct version number.

2002-01-06  Zack Weinberg  

	* GNUmakefile.in (PYTHON): Remove unnecessary use of 'env'.
	(clean): Don't use pushd and popd.  Don't delete documentation
	if we didn't build it.
	($(HTML_MANUALS)): Disable use of .tidyrc.
	* configure.in: Add Debian-specific locations of xml.dcl and
	DocBook stylesheets.  Fix typo.
	* configure: Regenerate.

2002-01-04  Mark Mitchell  

	* scripts/qm-release: New file.

2002-01-03  Mark Mitchell  

	* GNUmakefile.in (QM_TOOLS): Compute it automatically.

	* GNUmakefile.in (QM_TOOLS): New variable.
	(MAKEFILE_PRE_IN): Remove.
	(SCRIPTS): Calculate it automatically.
	(DTD_CATALOG): New variable.
	(COMMON_DTDS): Likewise.
	(TOOL_DTDS): Likewise.
	(COPIED_TOOL_DTDS): Likewise.
	(DTDS): Likewise.
	(JADECMD): Likewise.
	(DOCBOOK_MAIN): Remove.
	(DOCBOOK_SOURCES): Likewise.
	(HTMLDIR): Likewise.
	(HTMLINDEX): Likewise.
	(HTMLMANIFEST): Likewise.
	(HTMLTARBALL): Likewise.
	(PRINTDIR): Likewise.
	(PRINTTEX): Likewise.
	(PRINTPDF): Likewise.
	(HTML_MANUALS): New variable.
	(TEX_MANUALS): Likewise.
	(PDF_MANUALS): Likewise.
	(all): Add dependencies.
	(PYTHON_PACKAGES): Use -q option to setup.py.
	(DTD_CATALOG): New taret.
	(COPIED_TOOL_DTDS): Likewise.
	(clean): Clean up more stuff.
	(distclean): Remove GNUmakefile, not Makefile.
	(doc-html): Depend on HTML_MANUALS.
	(HTML_MANUALS): New rule.
	(TEX_MANUALS): Likewise.
	Adjust installation rules.
	* doc/qm-html.dsl: Rename to ...
	* doc/qm-sgml.dsl: ... this.
	* doc/qm-print.dsl: Rename to ...
	* doc/qm-tex.dsl: ... this.
	* doc/manual/introduction.xml: Remove.
	* doc/manual/manual.xml: Likewise.
	* doc/manual/test-manual.xml: Likewise.
	* doc/manual/test-tour.xml: Likewise.
	* doc/manual/track-email.xml: Likewise.
	* doc/manual/track-manual.xml: Likewise.
	* doc/manual/track-tour.xml: Likewise.
	* qm/.cvsignore: Add build.
	* qm/common.py (rmdir_recursively): Remove bogus assertion.
	(add_exit_function): Simplify.
	(_at_exit): Rename to ...
	(exit): This.
	* qm/diagnostic.py (load_messages): New function.
	(__initialize_module): Tweak.
	* qm/qm.sh: Fix typo in comment.
	* qm/setup.py: Automatically compute names of packages.
	* qm/setup_path.py.in: Add zope-dtml/ExtensionClass build
	directory to list of directories to search in build tree.
	* qm/test/.cvsignore: Remove qmtest-remote.
	* qm/test/cmdline.py (QMTest.commands_spec): Add "remote".
	(QMTest.Execute): Dispatch it.
	(QMTest.__ExecuteRemote): New method.
	* qm/test/qmtest-remote.py: Remove.
	* qm/test/qmtest.py: Use load_messages and qm.exit.
	* qm/test/classes/rsh_target.py (RSHTarget.Start): Use qmtest, not
	qmtest-remote, on the remote system.
	* qm/test/doc/.cvsignore: New file.
	* qm/test/doc/introduction.xml: Likewise.
	* qm/test/doc/manual.xml: Likewise.
	* qm/test/doc/reference.xml: Likewise.
	* qm/test/doc/tour.xml: Likewise.
	* qm/test/share/dtds/class-directory.dtd: New file.
	* qm/test/share/dtds/resource.dtd: Likewise.
	* qm/test/share/dtds/result.dtd: Likewise.
	* qm/test/share/dtds/suite.dtd: Likewise.
	* qm/test/share/dtds/target.dtd: Likewise.
	* qm/test/share/dtds/tdb-configuration.dtd: Likewise.
	* qm/test/share/dtds/test.dtd: Likewise.
	* qm/test/share/dtml/add-category.dtml: Likewise.
	* qm/test/share/dtml/add-prerequisite.dtml: Likewise.
	* qm/test/share/dtml/add-resource.dtml: Likewise.
	* qm/test/share/dtml/context.dtml: Likewise.
	* qm/test/share/dtml/dir.dtml: Likewise.
	* qm/test/share/dtml/expectations.dtml: Likewise.
	* qm/test/share/dtml/load-expected-results.dtml: Likewise.
	* qm/test/share/dtml/load-results.dtml: Likewise.
	* qm/test/share/dtml/navigation-bar.dtml: Likewise.
	* qm/test/share/dtml/new-suite.dtml: Likewise.
	* qm/test/share/dtml/new.dtml: Likewise.
	* qm/test/share/dtml/result.dtml: Likewise.
	* qm/test/share/dtml/results.dtml: Likewise.
	* qm/test/share/dtml/show.dtml: Likewise.
	* qm/test/share/dtml/suite.dtml: Likewise.
	* qm/test/share/messages/diagnostics.txt: Likewise.
	* qm/test/share/messages/help.txt: Likewise.
	* qm/test/share/tutorial/tdb/exec0.qmt: Likewise.
	* qm/test/share/tutorial/tdb/exec1.qmt: Likewise.
	* qm/test/share/tutorial/tdb/exec2.qmt: Likewise.
	* qm/test/share/tutorial/tdb/QMTest/configuration: Likewise.
	* qm/test/web/web.py (DefaultDtmlPage.__init__): New method.
	(QMTestServer.__Init__): Change path to manual.
	* qm/track/qmtrack.py: Use load_messages and qm.exit.
	* qm/track/server.py (WebServer.__init__): Change path to
	manual.
	* qm/track/doc/.cvsignore: New file.
	* qm/track/doc/email.xml: Likewise.
	* qm/track/doc/introduction.xml: Likewise.
	* qm/track/doc/manual.css: Likewise.
	* qm/track/doc/manual.xml: Likewise.
	* qm/track/doc/reference.xml: Likewise.
	* qm/track/doc/tour.xml: Likewise.
	* qm/track/share/dtds/idb-configuration.dtd: Likewise.
	* qm/track/share/dtds/issue-classes.dtd: Likewise.
	* qm/track/share/dtds/issue.dtd: Likewise.
	* qm/track/share/dtds/user.dtd: Likewise.
	* qm/track/share/dtds/users.xml.template: Likewise.
	* qm/track/share/dtds/users.xml.test-values: Likewise.
	* qm/track/share/dtml/add-category-name.dtml: Likewise.
	* qm/track/share/dtml/add-issue-class.dtml: Likewise.
	* qm/track/share/dtml/add-issue-field.dtml: Likewise.
	* qm/track/share/dtml/add-notification-address.dtml: Likewise.
	* qm/track/share/dtml/add-notification-uid.dtml: Likewise.
	* qm/track/share/dtml/config-idb.dtml: Likewise.
	* qm/track/share/dtml/configuration-navigation-bar.dtml: Likewise.
	* qm/track/share/dtml/history.dtml: Likewise.
	* qm/track/share/dtml/index.dtml: Likewise.
	* qm/track/share/dtml/issue-class.dtml: Likewise.
	* qm/track/share/dtml/navigation-bar.dtml: Likewise.
	* qm/track/share/messages/diagnostics.txt: Likewise.
	* qm/track/share/messages/help.txt: Likewise.
	* share/diagnostics/test-help.txt: Remove.
	* share/diagnostics/test.txt: Remove.
	* share/diagnostics/track-help.txt: Remove.
	* share/diagnostics/track.txt: Remove.
	* share/dtml/test: Remove all files.
	* share/dtml/track: Likewise.
	* share/tutorial/test: Likewise.
	* share/xml/.cvsignore: New file.
	* share/xml/CATALOG: Remove.
	* share/xml: Remove all DTDs.
	* tests/unit.qms/test.qms/classes.qms/scripttest1.qmt: Fix
	erroneous XML.

2002-01-02  Mark Mitchell  

	* .cvsignore (standard.mk): Remove.
	(Makefile): Likewise.
	(GNUmakefile): Ignore it.
	* Makefile.in: Rename to ...
	* GNUmakefile.in: ... this.
	* Makefile: New file.
	* standard.mk.in: Remove.
	* doc/.cvsignore (Makefile): Remove.
	* doc/Makefile.in: Remove.
	* doc/design/qmtest/.cvsignore (Makefile): Remove.
	* doc/manual/.cvsignore (Makefile): Remove.
	* doc/manual/Makefile.in: Remove.
	* doc/manual/track-manual.xml: Add user database description.
	* doc/manual/track-tour.xml: Update links.

	* qm/common.py (threading): Do not import it.
	(Lock): Remove.
	(MutexMixin): Likewise.
	* qm/test/cmdline.py (QMTest.__ExecuteRun): Use ExecutionEngine,
	not ExecutionThread.
	* qm/test/command_thread.py: New file.
	* qm/test/database.py (Database): Update documentation.
	* qm/test/execution_engine.py: New file.
	* qm/test/execution_thread.py (ExecutionThread): Move
	majority of contents to execution_engine.py.
	* qm/test/qmtest-remote.py (threading): Do not import it.
	* qm/test/target.py (CommandThread): Remove.
	* qm/test/xmldb.py (Database): Do not inherit from MutexMixin.
	Remove all references to locks and mutexes.
	* qm/test/classes/rsh_target.py (RSHTarget.NoteIdle): Remove.
	(RSHTarget._RecordResult): Mark the target idle when recording
	a test result.
	* qm/test/classes/thread_target.py (qm.test.command_thread):
	Import it.

	* standard.mk.in (TESTFLAGS): Remove.
	(test): Likewise.

2001-12-30  Mark Mitchell  

	* qm/attachment.py (AttachmentStore.GetSize): Provide a default
	implementation.
	(FileAttachmentStore): New class.
	* qm/common.py (load_class): Fix typo in error message.
	* qm/xmlutil.py (discard_node): New function.
	* qm/test/base.py (run_test): Remove.
	(set_up_resource): Likewise.
	(clean_up_resource): Likewise.
	* qm/test/cmdline.py (profile): Do not import it.
	(QMTest.profile_option_spec): Remove.
	(QMTest.GetTargets): Use SerialTarget if concurrent execution has
	not been requested.
	(QMTest.__ExecuteSummarize): Fix typo.
	(QMTest.__ExecuteRun): Improve keyboard interrupt handling.
	* qm/test/context.py (re): Import it.
	(Context.get): Fix typo.
	(Context.ValidateKey): Accept keys that include periods and
	underscores.
	(ContextWrapper.Get): Fix typo.
	* qm/test/database.py (ItemDescriptor._Execute): Allow the context
	to be None.
	(ResourceDescriptor.CleanUp): Do not take a context parameter.
	(Database.GetResource): Fix formatting.
	* qm/test/execution_thread.py: Rework substantially throughout.
	* qm/test/file_database.py (FileDatabase._GetLabels): Simplify.
	* qm/test/qmtest-remote.py: Rework for revised target interface.
	* qm/test/qmtest.py: Improve keyboard interrupt handling.
	* qm/test/resource.py (Resource.CleanUp): Do not take a context
	parameter.
	* qm/test/result.py (Result.RESOURCE): New constant.
	* qm/test/target.py (Target): Rework substantially.
	(CommandThread): Likewise.
	* qm/test/xmldb.py (Database.__init__): Remove create parameter.
	* qm/test/classes/classes.qmc: Add serial_target.SerialTarget.
	* qm/test/classes/rsh_target.py: Rework substantially.
	* qm/test/classes/temporary.py (TempDirectoryResource.SetUp):
	Remember the path to the directory created.
	(TempDirectoryResource.CleanUp): Remove context parameter.
	* qm/test/classes/thread_target.py: Rework substantially.
	* qm/test/web/web.py (QMTestServer.__init__): Do not register
	a download URL if the database does not have an attachment
	store.
	* share/diagnostics/test.txt: Adjust documentation.
	* doc/test-manual.xml: Update description of context.

2001-12-13  Mark Mitchell  

	* qm.spec.in (Release): Increment.

2001-12-12  Mark Mitchell  

	* doc/test-manual.xml: Fix typo.

2001-12-12  Mark Mitchell  

	* PyXML/.cvsignore: New file.
	* doc/qm-opl.xml: Update copyright date.
	* doc/manual/common-manual.xml: Tweak language.
	* doc/manual/test-manual.xml: Likewise.
	* doc/manual/test-tour.xml: Likewise.
	* qm/test/classes/python.py (ExecTest.Run): Fix typo in comment.
	* share/dtml/set.dtml: Clarify help documentation.

2001-12-11  Mark Mitchell  

	* qm/web.py (make_button_for_popup): Spell "resizeable" without
	the "e" in JavaScript code.
	(format_user_id): Likewise.
	* share/dtml/help.dtml (popup_manual): Likewise.
	* share/web/common.js (show_help): Likewise.
	(popup_manual): Likewise.

	* share/dtml/test/result.dtml: Sort the annotations.

2001-12-11  Mark Mitchell  

	* Makefile.in (doc-install): Do not assume $(INSTALL) understands
	wildcards.

2001-12-11  Mark Mitchell  

	* Makefile.in (SCRIPTS): Use backslashes on Windows.

2001-12-11  Mark Mitchell  

	* Makefile.in (install): Don't depend on install -D.
	(share-install): Likewise.
	* configure.in (AC_PROG_INSTALL): Remove.
	* configure: Regenerated.
	* standard.mk.in (INSTALL): Define explicitly.
	(INSTALL_DATA): Likewise.
	(INSTALL_PROGRAM): Likewise.
	(INSTALL_SCRIPT): Likewise.

2001-12-11  Mark Mitchell  

	* Makefile.in (SCRIPTS): Hardwire destination path.

2001-12-11  Mark Mitchell  

	* Makefile.in (PYTHON_PACKAGES_INSTALL): Do not attempt
	to set permissions on installed files.

2001-12-11  Mark Mitchell  

	* Makefile.in (RELINCDIR): New variable.
	(PYTHON_PACKAGES_INSTALL): Use it.
	* standard.mk.in (INSTALLINCDIR): New variable.
	(NATPREFIX): Likewise.

	* Makefile.in (PYTHON_PACKAGES_INSTALL): Use relative paths.
	* README: Document Distutils version required.

	* Makefile.in (SCRIPTS): Fix typo.
	* qm.spec (Release): Increment.

	* Makefile.in (SCRIPTS): Generate files with DOS line-ending
	convention under Windows.
	* doc/manual/introduction.xml: Expand.
	* doc/manual/test-tour.xml: Explain that Cygwin will not work with
	QMTest.

2001-12-10  Mark Mitchell  

	* qm/attachment.py (TemporaryAttachmentStore.HandleUploadRequest):
	Add type attribute to 
        
        '''

########################################################################
# functions
########################################################################

_temporary_location_prefix = "_temporary"


def make_temporary_location():
    """Return a unique location for temporary attachment data."""

    return _temporary_location_prefix + common.make_unique_tag()


def make_dom_node(attachment, document):
    """Create a DOM element node for this attachment.

    'document' -- A DOM document node in which to create the
    element.

    returns -- A DOM element node."""

    # Create an attachment element.
    node = document.createElement("attachment")
    # Is it a null attachment?
    if attachment is None:
        # Then that's it.
        return node

    mime_type = attachment.GetMimeType()

    # Create and add the description node.
    child = xmlutil.create_dom_text_element(
        document, "description", attachment.GetDescription())
    node.appendChild(child)
    # Create and add the MIME type node.
    child = xmlutil.create_dom_text_element(
        document, "mime-type", mime_type)
    node.appendChild(child)
    # Create and add the file name node.
    child = xmlutil.create_dom_text_element(
        document, "filename", attachment.GetFileName())
    node.appendChild(child)
    # Create a location element, to include attachment data by
    # reference.
    location = attachment.GetLocation()
    child = xmlutil.create_dom_text_element(document, "location", location)

    node.appendChild(child)
    return node


def from_dom_node(node, store):
    """Construct an attachment object from a DOM element node.

    'node' -- A DOM attachment element node.

    'store' -- The associated attachment store.
    
    returns -- An attachment instance.  The type is determined by
    'attachment_class'.

    If the attachment object requires additional context information to
    interpret the location (if it's specified in the attachment
    element), the caller must provide it directly to the object."""

    if len(node.childNodes) == 0:
        # It's an empty element, signifying a null attachment.
        return None

    # Extract the fixed fields; use a default value for each that is not
    # present. 
    description = xmlutil.get_child_text(node, "description", "")
    mime_type = xmlutil.get_child_text(
        node, "mime-type", "application/octet-stream")
    file_name = xmlutil.get_child_text(node, "filename", "")
    location = xmlutil.get_child_text(node, "location")
    # Construct the resulting attachment.
    return Attachment(mime_type, description, file_name, location, store)

########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/diagnostic.py0000664000076400007640000001440211107032237015477 0ustar  stefanstefan########################################################################
#
# File:   diagnostic.py
# Author: Alex Samuel
# Date:   2001-02-27
#
# Contents:
#   Code for managing and generating diagnostics.
#
# Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

"""Table-based diagnostic message generation.

Diagnostics are loaded from text files.  These files are laid out
according to special rules:

  - Lines beginning with a hash mark are ignored.

  - Each diagnostic begins with a line that contains an at sign (@) and
    a tag used to identify the diagnostic.

  - Subsequent text until the start of the next diagnostic is
    the diagnostic template.

  - Diagnostic templates may contain named-substition tokens as
    used by the Python % operator on a string.

  - Diagnostic messages are interpreted as structured text.

For example:

    # This line is a comment

    @ my first diagnostic
    The command you entered, '$(command)s', is bogus.  Please try again.

    @ my second diagnostic
    The value you specified, '$(value)d', is completely bogus.  Don't
    even bother trying again.

"""

########################################################################
# imports
########################################################################

import common
import os
import qm
import re
import string
import types

########################################################################
# classes
########################################################################

class DiagnosticSet:

    # Regular expression to match comment lines.
    __comment_regex = re.compile("^[ \t]*#.*$", re.MULTILINE)

    # Regular express that matches the start of a new diagnostic entry. 
    __separator_regex = re.compile("^@", re.MULTILINE)


    def __init__(self):
        """Initialize a new set of diagnostics."""

        self.__diagnostics = {}


    def ReadFromFile(self, path):
        """Load diagnostics from a file.

        'path' -- Path to the file containing diagnostics."""

        # Read the file.
        file = open(path, "r")
        contents = file.read()
        file.close()
        # Erase comment lines.
        contents = self.__comment_regex.sub("", contents)
        # Split the file's contents into entries.
        entries = self.__separator_regex.split(contents)
                
        for entry in entries:
            if not "\n" in entry:
                continue
            # The tag is everything up to the first newline.
            tag, message = string.split(entry, "\n", 1)
            # Clean up the tag and the diagnostic message.
            tag = string.strip(tag)
            message = string.strip(message)
            # Store it.
            self.__diagnostics[tag] = message


    def Generate(self, tag, severity="error", output=None, **substitutions):
        """Generate a diagnostic message.

        'tag' -- The tag of the diagnostic to generate.

        'severity' -- A string representing the severity of the
        diagnostic, for instance "warning" or "error".

        'output' -- If not 'None', the a file object to which the
        a full diagnostic is written.

        'substitutions' -- Named values for substitution into the
        diagnostic message.

        returns -- The bare diagnostic message."""
        
        substitutions = substitutions.copy()
        substitutions["program_name"] = common.program_name
        message = self.__diagnostics[tag] % substitutions
        if output is None:
            pass
        else:
            output.write("%s: %s: %s\n"
                         % (common.program_name, severity, message)) 
        return message


########################################################################
# Variables
########################################################################

__diagnostic_set = None
"""The 'DiagnosticSet' object from which diagnostics are generated."""

__help_set = None
"""The 'DiagnosticSet'object from which help text messages are
generated."""

########################################################################
# functions
########################################################################

def get_diagnostic_set():
    """Return the 'DiagnosticSet' containing warning/error messages.

    returns -- The 'DiagnosticSet' containing warning/error messages."""

    global __diagnostic_set
    if __diagnostic_set is None:
        __diagnostic_set = DiagnosticSet()
        __diagnostic_set.ReadFromFile(qm.get_share_directory("diagnostics",
                                                             "common.txt"))

    return __diagnostic_set


def get_help_set():
    """Return the 'DiagnosticSet' for help messages.

    returns -- The 'DiagnosticSet' containing help messages."""

    global __help_set
    if __help_set is None:
        __help_set = DiagnosticSet()
        __help_set.ReadFromFile(qm.get_share_directory("diagnostics",
                                                       "common-help.txt"))

    return __help_set

    
def message(tag, **substitutions):
    """Generate a diagnostic message."""

    return apply(get_diagnostic_set().Generate,
                 (tag, "message", None),
                 substitutions)


def error(tag, output=None, **substitutions):
    """Generate or emit an error diagnostic."""

    return apply(get_diagnostic_set().Generate,
                 (tag, "error", output, ),
                 substitutions)

    
def warning(tag, output=None, **substitutions):
    """Generate or emit a warning diagnostic."""

    return apply(get_diagnostic_set().Generate,
                 (tag, "warning", output, ),
                 substitutions)


def load_messages(tool):
    """Read messages that apply to 'tool'.

    'tool' -- A string giving the name of a QM tool."""

    # Load diagnostics.
    diagnostic_file = qm.get_share_directory('messages', 'diagnostics.txt')
    get_diagnostic_set().ReadFromFile(diagnostic_file)
    # Load help messages.
    diagnostic_file = qm.get_share_directory('messages', 'help.txt')
    get_help_set().ReadFromFile(diagnostic_file)
    
########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/0000775000076400007640000000000011122067201013753 5ustar  stefanstefanqmtest-2.4.1/qm/test/runnable.py0000664000076400007640000001074111107032225016137 0ustar  stefanstefan########################################################################
#
# File:   runnable.py
# Author: Mark Mitchell
# Date:   10/11/2002
#
# Contents:
#   QMTest Runnable class.
#
# Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

import qm
import qm.extension
from   qm.fields import AttachmentField, TupleField, SetField

########################################################################
# Classes
########################################################################

class Runnable(qm.extension.Extension):
    """A 'Runnable' can run on a 'Target'.

    'Runnable' is an abstract base class for 'Test' and 'Resource'."""

    class ResourceField(qm.fields.ChoiceField):
        """A 'ResourceField' contains the name of a resource.

        The exact format of the name depends on the test database in use."""

        def GetItems(self):

            database = qm.test.cmdline.get_qmtest().GetDatabase()
            return database.GetResourceIds()



    EXTRA_ID = "qmtest_id"
    """The name of the extra keyword argument to '__init__' that
    specifies the name of the test or resource."""
    
    EXTRA_DATABASE = "qmtest_database"
    """The name of the extra keyword argument to '__init__' that
    specifies the database containing the test or resource."""

    RESOURCE_FIELD_ID = "resources"
    """The name of the field that contains the resources on which this
    test or resource depends."""
    
    arguments = [
        qm.fields.SetField(
            ResourceField(
                name = RESOURCE_FIELD_ID,
                title = "Resources",
                description = \
                """Resources on which this test or resource depends.
                
                Before this test or resource is executed, the
                resources on which it depends will be set up.""",
                not_empty_text = "true",
                )),
        ]

    
    def __init__(self, arguments = None, **args):
        """Construct a new 'Runnable'.

        'arguments' -- As for 'Extension.__init__'.

        'args' -- As for 'Extension.__init__."""

        self.__id = args.pop(self.EXTRA_ID)
        self.__database = args.pop(self.EXTRA_DATABASE)
        if arguments: args.update(arguments)
        super(Runnable, self).__init__(**args)
        
        
        
    def GetId(self):
        """Return the name of this test or resource.

        'context' -- The 'Context' in which this entity is running.
        
        returns -- The name of this test or resource."""

        return self.__id


    def GetDatabase(self):
        """Return the 'Database' in which this test or resource is stored.

        returns -- The 'Database' in which this test or resource is
        stored."""

        return self.__database


    def GetAttachments(self):
        """Return the 'Attachment's to this 'Runnable'.

        returns -- A sequence consisting of the 'Attachment' objects
        associated with this runnable."""

        attachments = []
        for f in qm.extension.get_class_arguments(self.__class__):
            self.__GetAttachments(f,
                                  getattr(self, f.GetName()),
                                  attachments)
        return attachments


    def __GetAttachments(self, field, value, attachments):
        """Return the 'Attachments' that are part of 'field'.

        'field' -- The 'Field' being examined.

        'value' -- The value of that 'Field' in 'self'.

        'attachments' -- A sequence consisting of the attachments
        found so far.  Additional 'Attachment's are appended to this
        sequence by this function."""

        if isinstance(field, AttachmentField):
            attachments.append(getattr(self, field.GetName()))
        elif isinstance(field, TupleField):
            subfields = field.GetSubfields()
            for i in xrange(len(subfields)):
                self.__GetAttachments(subfields[i], value[i],
                                      attachments)
        elif isinstance(field, SetField):
            subfield = field.GetSubfields()[0]
            for i in xrange(len(value)):
                self.__GetAttachments(subfield, value[i],
                                      attachments)

        return
                
qmtest-2.4.1/qm/test/execution_engine.py0000664000076400007640000007546511107032225017677 0ustar  stefanstefan########################################################################
#
# File:   execution_engine.py
# Author: Mark Mitchell
# Date:   01/02/2002
#
# Contents:
#   ExecutionEngine
#
# Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

import os
import qm.common
import qm.queue
from   qm.test.base import *
import qm.test.cmdline
import qm.test.database
from   qm.test.expectation_database import ExpectationDatabase
from   qm.test.context import *
import qm.xmlutil
from   result import *
import select
import sys
import time

########################################################################
# Classes
########################################################################

class TerminationRequested(qm.common.QMException):
    """A target requested termination of the test loop."""
    
    pass



class ExecutionEngine:
    """A 'ExecutionEngine' executes tests.

    A 'ExecutionEngine' object handles the execution of a collection
    of tests.

    This class schedules the tests across one or more targets.

    The shedule is determined dynamically as the tests are executed
    based on which targets are idle and which are not.  Therefore, the
    testing load should be reasonably well balanced, even across a
    heterogeneous network of testing machines."""


    class __TestStatus(object):
        """A '__TestStatus' indicates whether or not a test has been run.

        The 'outcome' slot indicates whether the test has not be queued so
        that it can be run, has completed, or has not been processed at all.

        If there are tests that have this test as a prerequisite, they are
        recorded in the 'dependants' slot.

        Ever test passes through the following states, in the following
        order:

        1. Initial

           A test in this state has not yet been processed.  In this state,
           the 'outcome' slot is 'None'.

        2. Queued

           A test in this state has been placed on the stack of tests
           waiting to run.  In this state, the 'outcome' slot is
           'QUEUED'.  Such a test may be waiting for prerequisites to
           complete before it can run.

        3. Ready

           A test in this state is ready to run.  All prerequisites have
           completed, and their outcomes were as expected.  In this
           state, the 'outcome' slot is 'READY'.

        4. Finished

           A test in this state has finished running.  In this state, the
           'outcome' slot is one of the 'Result.outcomes'.

        The only exception to this order is that when an error is noted
        (like a failure to load a test from the database, or a
        prerequisite has an unexpected outcome) a test may jump to the
        "finished" state without passing through intermediate states."""

        __slots__ = "outcome", "dependants"

        QUEUED = "QUEUED"
        READY = "READY"

        def __init__(self):

            self.outcome = None
            self.dependants = None


        def GetState(self):
            """Return the state of this test.

            returns -- The state of this test, using the representation
            documented above."""
            
            return self.outcome
        
        
        def NoteQueued(self):
            """Place the test into the "queued" state."""

            assert self.outcome is None
            self.outcome = self.QUEUED


        def HasBeenQueued(self):
            """Returns true if the test was ever queued.

            returns -- True if the test has ever been on the queue.
            Such a test may be ready to run, or may in fact have already
            run to completion."""

            return self.outcome == self.QUEUED or self.HasBeenReady()


        def NoteReady(self):
            """Place the test into the "ready" state."""

            assert self.outcome is self.QUEUED
            self.outcome = self.READY
            

        def HasBeenReady(self):
            """Returns true if the test was ever ready.

            returns -- True if the test was every ready to run.  Such a
            test may have already run to completion."""

            return self.outcome == self.READY or self.IsFinished()


        def IsFinished(self):
            """Returns true if the test is in the "finished" state.

            returns -- True if this test is in the "finished" state."""

            return not (self.outcome is None
                        or self.outcome is self.READY
                        or self.outcome is self.QUEUED)


        def NoteDependant(self, test_id):
            """Note that 'test_id' depends on 'self'.

            'test_id' -- The name of a test.  That test has this test as a
            prerequisite."""

            if self.dependants is None:
                self.dependants = [test_id]
            else:
                self.dependants.append(test_id)


    # Every target is in one of three states: busy, idle, or starving.
    # A busy target is running tests, an idle target is ready to run
    # tests, and a starving target is ready to run tests, but no tests
    # are available for it to run.
    __TARGET_IDLE = "IDLE"
    __TARGET_BUSY = "BUSY"
    __TARGET_STARVING = "STARVING"


    def __init__(self,
                 database,
                 test_ids,
                 context,
                 targets,
                 result_streams = None,
                 expectations = None):
        """Set up a test run.

        'database' -- The 'Database' containing the tests that will be
        run.
        
        'test_ids' -- A sequence of IDs of tests to run.  Where
        possible, the tests are started in the order specified.
        
        'context' -- The context object to use when running tests.

        'targets' -- A sequence of 'Target' objects, representing
        targets on which tests may be run.

        'result_streams' -- A sequence of 'ResultStream' objects.  Each
        stream will be provided with results as they are available.

        'expectations' -- If not 'None', an ExpectationDatabase object."""

        self.__database = database
        self.__test_ids = test_ids
        self.__context = context
        self.__targets = targets
        if result_streams is not None:
            self.__result_streams = result_streams
        else:
            self.__result_streams = []
        if expectations is not None:
            self.__expectations = expectations
        else:
            self.__expectations = ExpectationDatabase(test_database = database)

        # There are no input handlers.
        self.__input_handlers = {}
        
        # There are no responses from the targets yet.
        self.__response_queue = qm.queue.Queue(0)
        # There no pending or ready tests yet.
        self.__running = 0

        self.__any_unexpected_outcomes = 0
        
        # Termination has not yet been requested.
        self.__terminated = 0
        

    def RequestTermination(self):
        """Request that the execution engine stop executing tests.

        Request that the execution thread be terminated.  Termination
        may take some time; tests that are already running will continue
        to run, for example."""

        self._Trace("Test loop termination requested.")
        self.__terminated = 1


    def _IsTerminationRequested(self):
        """Returns true if termination has been requested.

        returns -- True if no further tests should be executed.  If the
        value is -1, the execution engine should simply terminate
        gracefully."""

        return self.__terminated
    

    def Run(self):
        """Run the tests.

        This method runs the tests specified in the __init__
        function.

        returns -- True if any tests had unexpected outcomes."""

        # Write out run metadata.
        self._WriteInitialAnnotations()

        # Start all of the targets.
        for target in self.__targets:
            target.Start(self.__response_queue, self)

        # Run all of the tests.
        self._Trace("Starting test loop")
        try:
            try:
                self._RunTests()
            except:
                self._Trace("Test loop exited with exception: %s"
                            % str(sys.exc_info()))
                for rs in self.__result_streams:
                    rs.WriteAnnotation("qmtest.run.aborted", "true")
                raise
        finally:
            self._Trace("Test loop finished.")

            # Stop the targets.
            self._Trace("Stopping targets.")
            for target in self.__targets:
                target.Stop()

            # Read responses until there are no more.
            self._Trace("Checking for final responses.")
            while self.__CheckForResponse(wait=0):
                pass
            
            # Let all of the result streams know that the test run is
            # complete.
            end_time_str = qm.common.format_time_iso()
            for rs in self.__result_streams:
                rs.WriteAnnotation("qmtest.run.end_time", end_time_str)
                rs.Summarize()

        return self.__any_unexpected_outcomes


    def AddInputHandler(self, fd, function):
        """Add an input handler for 'fd'.

        'fd' -- A file descriptor, open for reading.

        'function' -- A callable object taking a single parameter.

        The execution engine will periodically monitor 'fd'.  When input
        is available, it will call 'function' passing it 'fd'."""

        self.__input_handlers[fd] = function
        

    def _RunTests(self):

        num_tests = len(self.__test_ids)

        # No tests have been started yet.
        self.__num_tests_started = 0

        self.__tests_iterator = iter(self.__test_ids)

        # A map from the tests we are supposed to run to their current
        # status.
        self.__statuses = {}
        for id in self.__test_ids:
            self.__statuses[id] = self.__TestStatus()

        # A stack of tests.  If a test has prerequisites, the
        # prerequisites will appear nearer to the top of the stack.
        self.__test_stack = []
        # A hash-table giving the names of the tests presently on the
        # stack.  The names are the keys; the values are unused.
        self.__ids_on_stack = {}

        # All targets are initially idle.
        self.__target_state = {}
        for target in self.__targets:
            self.__target_state[target] = self.__TARGET_IDLE
        self.__has_idle_targets = 1
        
        # Figure out what target groups are available.
        self.__target_groups = {}
        for target in self.__targets:
            self.__target_groups[target.GetGroup()] = None
        self.__target_groups = self.__target_groups.keys()
        
        # A hash-table indicating whether or not a particular target
        # pattern is matched by any of our targets.
        self.__pattern_ok = {}
        # A map from target groups to patterns satisfied by the group.
        self.__patterns = {}
        # A map from target patterns to lists of test descriptors ready
        # to run.
        self.__target_pattern_queues = {}
        
        while self.__num_tests_started < num_tests:
            # If the user interrupted QMTest, stop executing tests.
            if self._IsTerminationRequested():
                self._Trace("Terminating test loop as requested.")
                raise TerminationRequested, "Termination requested."

            # Process any responses and update the count of idle targets.
            while self.__CheckForResponse(wait=0):
                pass

            # Now look for idle targets.
            if not self.__has_idle_targets:
                # Block until one of the running tests completes.
                self._Trace("All targets are busy -- waiting.")
                self.__CheckForResponse(wait=1)
                self._Trace("Response received.")
                continue

            # Go through each of the idle targets, finding work for it
            # to do.
            self.__has_idle_targets = 0
            for target in self.__targets:
                if self.__target_state[target] != self.__TARGET_IDLE:
                    continue
                # Try to find work for the target.  If there is no
                # available work, the target is starving.
                if not self.__FeedTarget(target):
                    self.__target_state[target] = self.__TARGET_STARVING
                else:
                    # We gave the target some work, which may have
                    # changed its idle state, so update the status.
                    if target.IsIdle():
                        self.__target_state[target] = self.__TARGET_IDLE
                        self.__has_idle_targets = 1
                    else:
                        self.__target_state[target] = self.__TARGET_BUSY

        # Now every test that we're going to start has started; we just
        # have wait for them all to finish.
        self._Trace("Waiting for remaining tests to finish.")
        while self.__running:
            self.__CheckForResponse(wait=1)


    def __FeedTarget(self, target):
        """Run a test on 'target'

        'target' -- The 'Target' on which the test should be run.

        returns -- True, iff a test could be found to run on 'target'.
        False otherwise."""

        self._Trace("Looking for a test for target %s" % target.GetName())

        # See if there is already a ready-to-run test for this target.
        for pattern in self.__patterns.get(target.GetGroup(), []):
            tests = self.__target_pattern_queues.get(pattern, [])
            if tests:
                descriptor = tests.pop()
                break
        else:
            # There was no ready-to-run test queued, so try to find one
            # another one.
            descriptor = self.__FindRunnableTest(target)
            if descriptor is None:
                # There really are no more tests ready to run.
                return 0
                
        target_name = target.GetName()
        test_id = descriptor.GetId()
        self._Trace("Running %s on %s" % (test_id, target_name))
        assert self.__statuses[test_id].GetState() == self.__TestStatus.READY
        self.__num_tests_started += 1
        self.__running += 1
        target.RunTest(descriptor, self.__context)
        return 1


    def __FindRunnableTest(self, target):
        """Return a test that is ready to run.

        'target' -- The 'Target' on which the test will run.
        
        returns -- the 'TestDescriptor' for the next available ready
        test, or 'None' if no test could be found that will run on
        'target'.

        If a test with unsatisfied prerequisites is encountered, the
        test will be pushed on the stack and the prerequisites processed
        recursively."""

        while 1:
            if not self.__test_stack:
                # We ran out of prerequisite tests, so pull a new one
                # off the user's list.
                try:
                    test_id = self.__tests_iterator.next()
                except StopIteration:
                    # We're entirely out of fresh tests; give up.
                    return None
                if self.__statuses[test_id].HasBeenQueued():
                    # This test has already been handled (probably
                    # because it's a prereq of a test already seen).
                    continue
                # Try to add the new test to the stack.
                if not self.__AddTestToStack(test_id):
                    # If that failed, look for another test.
                    continue
                self._Trace("Added new test %s to stack" % test_id)

            descriptor, prereqs = self.__test_stack[-1]
            # First look at the listed prereqs.
            if prereqs:
                new_test_id = prereqs.pop()
                # We must filter tests that are already in the process
                # here; if we were to do it earlier, we would be in
                # danger of being confused by dependency graphs like
                # A->B, A->C, B->C, where we can't know ahead of time
                # that A's dependence on C is unnecessary.
                if self.__statuses[new_test_id].HasBeenQueued():
                    # This one is already in process.  This might
                    # indicate a dependency cycle, so check for that
                    # now.
                    if new_test_id in self.__ids_on_stack:
                        self._Trace("Cycle detected (%s)"
                                    % (new_test_id,))
                        self.__AddUntestedResult \
                                 (new_test_id,
                                  qm.message("dependency cycle"))
                    continue
                else:
                    self.__AddTestToStack(new_test_id)
                    continue
            else:
                # Remove the test from the stack.
                test_id = descriptor.GetId()
                del self.__ids_on_stack[test_id]
                self.__test_stack.pop()

                # Check to see if the test is already ready to run, or
                # has completed.  The first case occurs when the test
                # has prerequisites that have completed after it was
                # placed on the stack; the second occurs when a test
                # is marked UNTESTED after a cycle is detected.
                if self.__statuses[test_id].HasBeenReady():
                    continue

                # Now check the prerequisites.
                prereqs = self.__GetPendingPrerequisites(descriptor)
                # If one of the prerequisites failed, the test will have
                # been marked UNTESTED.  Keep looking for a runnable
                # test.
                if prereqs is None:
                    continue
                # If there are prerequisites, request notification when
                # they have completed.
                if prereqs:
                    for p in prereqs:
                        self.__statuses[p].NoteDependant(test_id)
                    # Keep looking for a runnable test.                        
                    continue

                # This test is ready to run.  See if it can run on
                # target.
                if not target.IsInGroup(descriptor.GetTargetGroup()):
                    # This test can't be run on this target, but it can be
                    # run on another target.
                    self.__AddToTargetPatternQueue(descriptor)
                    continue
                    
                self.__statuses[descriptor.GetId()].NoteReady()
                return descriptor


    def __AddTestToStack(self, test_id):
        """Adds 'test_id' to the stack of current tests.

        returns -- True if the test was added to the stack; false if the
        test could not be loaded.  In the latter case, an 'UNTESTED'
        result is recorded for the test."""
        
        self._Trace("Trying to add %s to stack" % test_id)

        # Update test status.
        self.__statuses[test_id].NoteQueued()

        # Load the descriptor.
        descriptor = self.__GetTestDescriptor(test_id)
        if not descriptor:
            return 0

        # Check that all the prerequisites listed are actually present
        # in the database.  We may not actually run all of them, but if
        # they're completely missing, that indicates a problem with
        # either the descriptor or the database.
        for p in descriptor.GetPrerequisites():
            if not self.__database.HasTest(p):
                self.__AddUntestedResult(
                    test_id,
                    qm.message("prerequisite not in database",
                               prerequisite = p)
                    )
                return 0
        
        # Ignore prerequisites that are not going to be run at all.
        prereqs_iter = iter(descriptor.GetPrerequisites())
        relevant_prereqs = filter(self.__statuses.has_key, prereqs_iter)

        # Store the test on the stack.
        self.__ids_on_stack[test_id] = None
        self.__test_stack.append((descriptor, relevant_prereqs))

        return 1

        
    def __AddToTargetPatternQueue(self, descriptor):
        """A a test to the appropriate target pattern queue.

        'descriptor' -- A 'TestDescriptor'.

        Adds the test to the target pattern queue indicated in the
        descriptor."""

        test_id = descriptor.GetId()
        self.__statuses[test_id].NoteReady()

        pattern = descriptor.GetTargetGroup()

        # If we have not already determined whether or not this pattern
        # matches any of the targets, do so now.
        if not self.__pattern_ok.has_key(pattern):
            self.__pattern_ok[pattern] = 0
            for group in self.__target_groups:
                if re.match(pattern, group):
                    self.__pattern_ok[pattern] = 1
                    patterns = self.__patterns.setdefault(group, [])
                    patterns.append(pattern)
        # If none of the targets can run this test, mark it untested.
        if not self.__pattern_ok[pattern]:
            self.__AddUntestedResult(test_id,
                                     "No target matching %s." % pattern)
            return

        queue = self.__target_pattern_queues.setdefault(pattern, [])
        queue.append(descriptor)


    def __GetPendingPrerequisites(self, descriptor):
        """Return pending prerequisite tests for 'descriptor'.

        'descriptor' -- A 'TestDescriptor'.
        
        returns -- A list of prerequisite test ids that have to
        complete, or 'None' if one of the prerequisites had an
        unexpected outcome."""

        needed = []

        prereqs = descriptor.GetPrerequisites()
        for prereq_id, outcome in prereqs.iteritems():
            try:
                prereq_status = self.__statuses[prereq_id]
            except KeyError:
                # This prerequisite is not being run at all, so skip
                # it.
                continue

            if prereq_status.IsFinished():
                prereq_outcome = prereq_status.outcome
                if outcome != prereq_outcome:
                    # Failed prerequisite.
                    self.__AddUntestedResult \
                        (descriptor.GetId(),
                         qm.message("failed prerequisite"),
                         {'qmtest.prequisite': prereq_id,
                          'qmtest.outcome': prereq_outcome,
                          'qmtest.expected_outcome': outcome })
                    return None
            else:
                # This prerequisite has not yet completed.
                needed.append(prereq_id)

        return needed


    def __AddResult(self, result):
        """Report the result of running a test or resource.
        
        'result' -- A 'Result' object representing the result of running
        a test or resource."""

        # Output a trace message.
        id = result.GetId()
        self._Trace("Recording %s result for %s." % (result.GetKind(), id))

        # Find the target with the name indicated in the result.
        if result.has_key(Result.TARGET):
            for target in self.__targets:
                if target.GetName() == result[Result.TARGET]:
                    break
            else:
                assert 0, ("No target %s exists (test id: %s)"
                           % (result[Result.TARGET], id))
        else:
            # Not all results will have associated targets.  If the
            # test was not run at all, there will be no associated
            # target.
            target = None

        # Having no target is a rare occurrence; output a trace message.
        if not target:
            self._Trace("No target for %s." % id)

        # This target might now be idle.
        if (target and target.IsIdle()):
            # Output a trace message.
            self._Trace("Target is now idle.\n")
            self.__target_state[target] = self.__TARGET_IDLE
            self.__has_idle_targets = 1
            
        # Only tests have expectations or scheduling dependencies.
        if result.GetKind() == Result.TEST:
            # Record the outcome for this test.
            test_status = self.__statuses[id]
            test_status.outcome = result.GetOutcome()

            # If there were tests waiting for this one to complete, they
            # may now be ready to execute.
            if test_status.dependants:
                for dependant in test_status.dependants:
                    if not self.__statuses[dependant].HasBeenReady():
                        descriptor = self.__GetTestDescriptor(dependant)
                        if not descriptor:
                            continue
                        prereqs = self.__GetPendingPrerequisites(descriptor)
                        if prereqs is None:
                            continue
                        if not prereqs:
                            # All prerequisites ran and were satisfied.
                            # This test can now run.
                            self.__AddToTargetPatternQueue(descriptor)
                # Free the memory consumed by the list.
                del test_status.dependants

            # Check for unexpected outcomes.
            if result.GetKind() == Result.TEST:
                if (self.__expectations.Lookup(id).GetOutcome()
                    != result.GetOutcome()):
                    self.__any_unexpected_outcomes = 1

            # Any targets that were starving may now be able to find
            # work.
            for t in self.__targets:
                if self.__target_state[t] == self.__TARGET_STARVING:
                    self.__target_state[t] = self.__TARGET_IDLE
            
        # Output a trace message.
        self._Trace("Writing result for %s to streams." % id)

        # Report the result.
        for rs in self.__result_streams:
            rs.WriteResult(result)


    def __CheckForResponse(self, wait):
        """See if any of the targets have completed a task.

        'wait' -- If false, this function returns immediately if there
        is no available response.  If 'wait' is true, this function
        continues to wait until a response is available.

        returns -- True iff a response was received."""

        while 1:
            try:
                # Read a reply from the response_queue.
                result = self.__response_queue.get(0)
                # Output a trace message.
                self._Trace("Got %s result for %s from queue."
                             % (result.GetKind(), result.GetId()))
                # Record the result.
                self.__AddResult(result)
                if result.GetKind() == Result.TEST:
                    assert self.__running > 0
                    self.__running -= 1
                # Output a trace message.
                self._Trace("Recorded result.")
                return result
            except qm.queue.Empty:
                # If there is nothing in the queue, then this exception will
                # be thrown.
                if not wait:
                    return None
                
                # Give other threads and processes a chance to run.
                if self.__input_handlers:
                    # See if there is any input that might indicate that
                    # work has been done.
                    fds = self.__input_handlers.keys()
                    fds = select.select (fds, [], [], 0.1)[0]
                    for fd in fds:
                        self.__input_handlers[fd](fd)
                else:
                    time.sleep(0.1)
                
                # There may be a response now.
                continue


    def __AddUntestedResult(self, test_name, cause, annotations={},
                            exc_info = None):
        """Add a 'Result' indicating that 'test_name' was not run.

        'test_name' -- The label for the test that could not be run.

        'cause' -- A string explaining why the test could not be run.

        'annotations' -- A map from strings to strings giving
        additional annotations for the result.

        'exc_info' -- If this test could not be tested due to a thrown
        exception, 'exc_info' is the result of 'sys.exc_info()' when the
        exception was caught.  'None' otherwise."""

        # Remember that this test was started.
        self.__num_tests_started += 1

        # Create and record the result.
        result = Result(Result.TEST, test_name, annotations = annotations)
        if exc_info:
            result.NoteException(exc_info, cause, Result.UNTESTED)
        else:
            result.SetOutcome(Result.UNTESTED, cause)
        self.__AddResult(result)


    ### Utility methods.

    def __GetTestDescriptor(self, test_id):
        """Return the 'TestDescriptor' for 'test_id'.

        returns -- The 'TestDescriptor' for 'test_id', or 'None' if the
        descriptor could not be loaded.

        If the database cannot load the descriptor, an 'UNTESTED' result
        is recorded for 'test_id'."""

        try:
            return self.__database.GetTest(test_id)
        except:
            self.__AddUntestedResult(test_id,
                                     "Could not load test.",
                                     exc_info = sys.exc_info())
            return None
        
        
    def _Trace(self, message):
        """Write a trace 'message'.

        'message' -- A string to be output as a trace message."""

        if __debug__:
            tracer = qm.test.cmdline.get_qmtest().GetTracer()
            tracer.Write(message, "exec")

    
    def _WriteInitialAnnotations(self):

        # Calculate annotations.
        start_time_str = qm.common.format_time_iso()

        try:
            username = qm.common.get_username()
        except:
            username = None

        try:
            uname = " ".join(os.uname())
        except:
            uname = None
        try:
            userid = str(qm.common.get_userid())
        except:
            userid = None

        args_str = " ".join(sys.argv)

        # Write them.
        for rs in self.__result_streams:
            rs.WriteAllAnnotations(self.__context)
            rs.WriteAnnotation("qmtest.run.start_time", start_time_str)
            if username is not None:
                rs.WriteAnnotation("qmtest.run.username", username)
            if userid is not None:
                rs.WriteAnnotation("qmtest.run.userid", userid)
            rs.WriteAnnotation("qmtest.run.version", qm.version)
            if uname is not None:
                rs.WriteAnnotation("qmtest.run.uname", uname)
            rs.WriteAnnotation("qmtest.run.command_line", args_str)


########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/cmdline.py0000664000076400007640000020532411120045062015745 0ustar  stefanstefan########################################################################
#
# File:   cmdline.py
# Author: Alex Samuel
# Date:   2001-03-16
#
# Contents:
#   QMTest command processing
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

import base
import database
import os
import qm
import qm.attachment
import qm.cmdline
import qm.platform
from   qm.extension import get_extension_class_name, get_class_description
from   qm.test import test
from   qm.test.result import Result
from   qm.test.context import *
from   qm.test.execution_engine import *
from   qm.test.result_stream import ResultStream
from   qm.test.runnable import Runnable
from   qm.test.suite import Suite
from   qm.test.report import ReportGenerator
from   qm.test.classes.dir_run_database import *
from   qm.test.expectation_database import ExpectationDatabase
from   qm.test.classes.previous_testrun import PreviousTestRun
from   qm.trace import *
from   qm.test.web.web import QMTestServer
import qm.structured_text
import qm.xmlutil
import Queue
import random
from   result import *
import signal
import string
import sys
import xml.sax

########################################################################
# Variables
########################################################################

_the_qmtest = None
"""The global 'QMTest' object."""

########################################################################
# Functions
########################################################################

def _make_comma_separated_string (items, conjunction):
    """Return a string consisting of the 'items', separated by commas.

    'items' -- A list of strings giving the items in the list.

    'conjunction' -- A string to use before the final item, if there is
    more than one.

    returns -- A string consisting all of the 'items', separated by
    commas, and with the 'conjunction' before the final item."""
    
    s = ""
    need_comma = 0
    # Go through almost all of the items, adding them to the
    # comma-separated list.
    for i in items[:-1]:
        # Add a comma if this isn't the first item in the list.
        if need_comma:
            s += ", "
        else:
            need_comma = 1
        # Add this item.
        s += "'%s'" % i
    # The last item is special, because we need to include the "or".
    if items:
        i = items[-1]
        if need_comma:
            s += ", %s " % conjunction
        s += "'%s'" % i

    return s

########################################################################
# Classes
########################################################################

class QMTest:
    """An instance of QMTest."""

    __extension_kinds_string \
         = _make_comma_separated_string(base.extension_kinds, "or")
    """A string listing the available extension kinds."""

    db_path_environment_variable = "QMTEST_DB_PATH"
    """The environment variable specifying the test database path."""

    summary_formats = ("brief", "full", "stats", "batch", "none")
    """Valid formats for result summaries."""

    context_file_name = "context"
    """The default name of a context file."""
    
    expectations_file_name = "expectations.qmr"
    """The default name of a file containing expectations."""
    
    results_file_name = "results.qmr"
    """The default name of a file containing results."""

    target_file_name = "targets"
    """The default name of a file containing targets."""
    
    help_option_spec = (
        "h",
        "help",
        None,
        "Display usage summary."
        )

    version_option_spec = (
        None,
        "version",
        None,
        "Display version information."
        )
    
    db_path_option_spec = (
        "D",
        "tdb",
        "PATH",
        "Path to the test database."
        )

    extension_output_option_spec = (
        "o",
        "output",
        "FILE",
        "Write the extension to FILE.",
        )

    extension_id_option_spec = (
        "i",
        "id",
        "NAME",
        "Write the extension to the database as NAME.",
        )
        
    output_option_spec = (
        "o",
        "output",
        "FILE",
        "Write test results to FILE (- for stdout)."
        )

    no_output_option_spec = (
        None,
        "no-output",
        None,
        "Don't generate test results."
        )

    outcomes_option_spec = (
        "O",
        "outcomes",
        "FILE",
        "Use expected outcomes in FILE."
        )

    expectations_option_spec = (
        "e",
        "expectations",
        "FILE",
        "Use expectations in FILE."
        )

    context_option_spec = (
        "c",
        "context",
        "KEY=VALUE",
        "Add or override a context property."
        )

    context_file_spec = (
        "C",
        "load-context",
        "FILE",
        "Read context from a file (- for stdin)."
        )

    daemon_option_spec = (
        None,
        "daemon",
        None,
        "Run as a daemon."
        )
        
    port_option_spec = (
        "P",
        "port",
        "PORT",
        "Server port number."
        )

    address_option_spec = (
        "A",
        "address",
        "ADDRESS",
        "Local address."
        )

    log_file_option_spec = (
        None,
        "log-file",
        "PATH",
        "Log file name."
        )

    no_browser_option_spec = (
        None,
        "no-browser",
        None,
        "Do not open a new browser window."
        )

    pid_file_option_spec = (
        None,
        "pid-file",
        "PATH",
        "Process ID file name."
        )
    
    concurrent_option_spec = (
        "j",
        "concurrency",
        "COUNT",
        "Execute tests in COUNT concurrent threads."
        )

    targets_option_spec = (
        "T",
        "targets",
        "FILE",
        "Use FILE as the target specification file."
        )

    random_option_spec = (
        None,
        "random",
        None,
        "Run the tests in a random order."
        )

    rerun_option_spec = (
        None,
        "rerun",
        "FILE",
        "Rerun the tests that failed."
        )
    
    seed_option_spec = (
        None,
        "seed",
        "INTEGER",
        "Seed the random number generator."
        )

    format_option_spec = (
        "f",
        "format",
        "FORMAT",
        "Specify the summary format."
        )

    result_stream_spec = (
        None,
        "result-stream",
        "CLASS-NAME",
        "Specify the results file format."
        )
        
    annotation_option_spec = (
        "a",
        "annotate",
        "NAME=VALUE",
        "Set an additional annotation to be written to the result stream(s)."
        )

    tdb_class_option_spec = (
        "c",
        "class",
        "CLASS-NAME",
        "Specify the test database class.",
        )

    attribute_option_spec = (
        "a",
        "attribute",
        "NAME",
        "Get an attribute of the extension class."
        )

    set_attribute_option_spec = (
        "a",
        "attribute",
        "KEY=VALUE",
        "Set an attribute of the extension class."
        )

    extension_kind_option_spec = (
        "k",
        "kind",
        "EXTENSION-KIND",
        "Specify the kind of extension class."
        )

    report_output_option_spec = (
        "o",
        "output",
        "FILE",
        "Write test report to FILE (- for stdout)."
        )

    report_flat_option_spec = (
        "f",
        "flat",
        None,
        """Generate a flat listing of test results, instead of reproducing the
        database directory tree in the report."""
        )

    results_option_spec = (
        "R",
        "results",
        "DIRECTORY",
        "Read in all results (*.qmr) files from DIRECTORY."
        )

    list_long_option_spec = (
        "l",
        "long",
        None,
        "Use a detailed output format."
        )

    list_details_option_spec = (
        "d",
        "details",
        None,
        "Display details for individual items."
        )

    list_recursive_option_spec = (
        "R",
        "recursive",
        None,
        "Recursively list the contents of directories."
        )
    
    # Groups of options that should not be used together.
    conflicting_option_specs = (
        ( output_option_spec, no_output_option_spec ),
        ( concurrent_option_spec, targets_option_spec ),
        ( extension_output_option_spec, extension_id_option_spec ),
        ( expectations_option_spec, outcomes_option_spec ),
        )

    global_options_spec = [
        help_option_spec,
        version_option_spec,
        db_path_option_spec,
        ]

    commands_spec = [
        ("create",
         "Create (or update) an extension.",
         "EXTENSION-KIND CLASS-NAME(ATTR1 = 'VAL1', ATTR2 = 'VAL2', ...)",
         """Create (or update) an extension.

         The EXTENSION-KIND indicates what kind of extension to
         create; it must be one of """ + __extension_kinds_string + """.

         The CLASS-NAME indicates the name of the extension class, or
         the name of an existing extension object.  If the CLASS-NAME
         is the name of a extension in the test database, then the 

         In the former case, it must have the form 'MODULE.CLASS'.  For
         a list of available extension classes use "qmtest extensions".
         If the extension class takes arguments, those arguments can be
         specified after the CLASS-NAME as show above.  In the latter
         case,

         Any "--attribute" options are processed before the arguments
         specified after the class name.  Therefore, the "--attribute"
         options can be overridden by the arguments provided after the
         CLASS-NAME.  If no attributes are specified, the parentheses
         following the 'CLASS-NAME' can be omitted.

         If the "--id" option is given, the extension is written to the
         database.  Otherwise, if the "--output" option is given, the
         extension is written as XML to the file indicated.  If neither
         option is given, the extension is written as XML to the
         standard output.""",
         ( set_attribute_option_spec,
           help_option_spec,
           extension_id_option_spec,
           extension_output_option_spec
           ),
         ),
           
        ("create-target",
         "Create (or update) a target specification.",
         "NAME CLASS [ GROUP ]",
         "Create (or update) a target specification.",
         ( set_attribute_option_spec,
           help_option_spec,
           targets_option_spec
           )
         ),

        ("create-tdb",
         "Create a new test database.",
         "",
         "Create a new test database.",
         ( help_option_spec,
           tdb_class_option_spec,
           set_attribute_option_spec)
         ),

        ("gui",
         "Start the QMTest GUI.",
         "",
         "Start the QMTest graphical user interface.",
         (
           address_option_spec,
           concurrent_option_spec,
           context_file_spec,
           context_option_spec,
           daemon_option_spec,
           help_option_spec,
           log_file_option_spec,
           no_browser_option_spec,
           pid_file_option_spec,
           port_option_spec,
           outcomes_option_spec,
           targets_option_spec,
           results_option_spec
           )
         ),

        ("extensions",
         "List extension classes.",
         "",
         """
List the available extension classes.

Use the '--kind' option to limit the classes displayed to test classes,
resource classes, etc.  The parameter to '--kind' can be one of """  + \
         __extension_kinds_string + "\n",
         (
           extension_kind_option_spec,
           help_option_spec,
         )
        ),

        ("describe",
         "Describe an extension.",
         "EXTENSION-KIND NAME",
         """Display details for the specified extension.""",
         (
           attribute_option_spec,
           list_long_option_spec,
           help_option_spec,
         )
        ),

        ("help",
         "Display usage summary.",
         "",
         "Display usage summary.",
         ()
         ),

        ("ls",
         "List database contents.",
         "[ NAME ...  ]",
         """
         List items stored in the database.

         If no arguments are provided, the contents of the root
         directory of the database are displayed.  Otherwise, each of
         the database is searched for each of the NAMEs.  If the item
         found is a directory then the contents of the directory are
         displayed.
         """,
         (
           help_option_spec,
           list_long_option_spec,
           list_details_option_spec,
           list_recursive_option_spec,
         ),
         ),
         
        ("register",
         "Register an extension class.",
         "KIND CLASS",
         """
Register an extension class with QMTest.  KIND is the kind of extension
class to register; it must be one of """ + __extension_kinds_string + """

The CLASS gives the name of the class in the form 'module.class'.

QMTest will search the available extension class directories to find the
new CLASS.  QMTest looks for files whose basename is the module name and
whose extension is either '.py', '.pyc', or '.pyo'.

QMTest will then attempt to load the extension class.  If the extension
class cannot be loaded, QMTest will issue an error message to help you
debug the problem.  Otherwise, QMTest will update the 'classes.qmc' file
in the directory containing the module to mention your new extension class.
         """,
         (help_option_spec,)
         ),
        
        ("remote",
         "Run QMTest as a remote server.",
         "",
         """
Runs QMTest as a remote server.  This mode is only used by QMTest
itself when distributing tests across multiple machines.  Users
should not directly invoke QMTest with this option.
         """,
         (help_option_spec,)
         ),

        ("report",
         "Generate report from one or more test results.",
         "[ result [-e expected] ]+",
         """
Generates a test report. The arguments are result files each optionally
followed by '-e' and an expectation file. This command attempts to reproduce
the test database structure, and thus requires the '--tdb' option. To generate
a flat test report specify the '--flat' option.
         """,
         (help_option_spec,
          report_output_option_spec,
          report_flat_option_spec)
         ),

        ("run",
         "Run one or more tests.",
         "[ ID ... ]",
         """
Runs tests.  Optionally, generates a summary of the test run and a
record of complete test results.  You may specify test IDs and test
suite IDs to run; omit arguments to run the entire test database.

Test results are written to "results.qmr".  Use the '--output' option to
specify a different output file, or '--no-output' to supress results.

Use the '--format' option to specify the output format for the summary.
Valid formats are %s.
         """ % _make_comma_separated_string(summary_formats, "and"),
         (
           annotation_option_spec,
           concurrent_option_spec,
           context_file_spec,
           context_option_spec,
           format_option_spec,
           help_option_spec,
           no_output_option_spec,
           outcomes_option_spec,
           expectations_option_spec,
           output_option_spec,
           random_option_spec,
           rerun_option_spec,
           result_stream_spec,
           seed_option_spec,
           targets_option_spec,
           )
         ),

        ("summarize",
         "Summarize results from a test run.",
         "[FILE [ ID ... ]]",
         """
Loads a test results file and summarizes the results.  FILE is the path
to the results file.  Optionally, specify one or more test or suite IDs
whose results are shown.  If none are specified, shows all tests that
did not pass.

Use the '--format' option to specify the output format for the summary.
Valid formats are %s.
         """ % _make_comma_separated_string(summary_formats, "and"),
         ( help_option_spec,
           format_option_spec,
           outcomes_option_spec,
           expectations_option_spec,
           output_option_spec,
           result_stream_spec)
         ),

        ]

    __version_output = \
        ("QMTest %s\n" 
         "Copyright (C) 2002 - 2007 CodeSourcery, Inc.\n"
         "QMTest comes with ABSOLUTELY NO WARRANTY\n"
         "For more information about QMTest visit http://www.qmtest.com\n")
    """The string printed when the --version option is used.

    There is one fill-in, for a string, which should contain the version
    number."""
    
    def __init__(self, argument_list, path):
        """Construct a new QMTest.

        Parses the argument list but does not execute the command.

        'argument_list' -- The arguments to QMTest, not including the
        initial argv[0].

        'path' -- The path to the QMTest executable."""

        global _the_qmtest
        
        _the_qmtest = self
        
        # Use the stadard stdout and stderr streams to emit messages.
        self._stdout = sys.stdout
        self._stderr = sys.stderr
        
        # Build a trace object.
        self.__tracer = Tracer()

        # Build a command-line parser for this program.
        self.__parser = qm.cmdline.CommandParser(
            "qmtest",
            self.global_options_spec,
            self.commands_spec,
            self.conflicting_option_specs)
        # Parse the command line.
        components = self.__parser.ParseCommandLine(argument_list)
        # Unpack the results.
        ( self.__global_options,
          self.__command,
          self.__command_options,
          self.__arguments
          ) = components

        # If available, record the path to the qmtest executable.
        self.__qmtest_path = path
        
        # We have not yet computed the set of available targets.
        self.targets = None

        # The result stream class used for results files is the pickling
        # version.
        self.__file_result_stream_class_name \
            = "pickle_result_stream.PickleResultStream"
        # The result stream class used for textual feed back.
        self.__text_result_stream_class_name \
            = "text_result_stream.TextResultStream"
        # The expected outcomes have not yet been loaded.
        self.__expected_outcomes = None


    def __del__(self):
        """Clean up global variables."""
        
        test.set_targets([])


    def HasGlobalOption(self, option):
        """Return true if 'option' was specified as a global command.

        'command' -- The long name of the option, but without the
        preceding "--".

        returns -- True if the option is present."""

        return option in map(lambda x: x[0], self.__global_options)
    
        
    def GetGlobalOption(self, option, default=None):
        """Return the value of global 'option', or 'default' if omitted."""

        for opt, opt_arg in self.__global_options:
            if opt == option:
                return opt_arg
        return default


    def HasCommandOption(self, option):
        """Return true if command 'option' was specified."""

        for opt, opt_arg in self.__command_options:
            if opt == option:
                return 1
        return 0
    

    def GetCommandOption(self, option, default = None):
        """Return the value of command 'option'.

        'option' -- The long form of an command-specific option.

        'default' -- The default value to be returned if the 'option'
        was not specified.  This option should be the kind of an option
        that takes an argument.

        returns -- The value specified by the option, or 'default' if
        the option was not specified."""

        for opt, opt_arg in self.__command_options:
            if opt == option:
                return opt_arg
        return default


    def Execute(self):
        """Execute the command.

        returns -- 0 if the command was executed successfully.  1 if
        there was a problem or if any tests run had unexpected outcomes."""

        # If --version was given, print the version number and exit.
        # (The GNU coding standards require that the program take no
        # further action after seeing --version.)
        if self.HasGlobalOption("version"):
            self._stdout.write(self.__version_output % qm.version)
            return 0
        # If the global help option was specified, display it and stop.
        if (self.GetGlobalOption("help") is not None 
            or self.__command == "help"):
            self._stdout.write(self.__parser.GetBasicHelp())
            return 0
        # If the command help option was specified, display it and stop.
        if self.GetCommandOption("help") is not None:
            self.__WriteCommandHelp(self.__command)
            return 0

        # Make sure a command was specified.
        if self.__command == "":
            raise qm.cmdline.CommandError, qm.error("missing command")

        # Look in several places to find the test database:
        #
        # 1. The command-line.
        # 2. The QMTEST_DB_PATH environment variable.
        # 3. The current directory.
        db_path = self.GetGlobalOption("tdb")
        if not db_path:
            if os.environ.has_key(self.db_path_environment_variable):
                db_path = os.environ[self.db_path_environment_variable]
            else:
                db_path = "."
        # If the path is not already absolute, make it into an
        # absolute path at this point.
        if not os.path.isabs(db_path):
            db_path = os.path.join(os.getcwd(), db_path)
        # Normalize the path so that it is easy for the user to read
        # if it is emitted in an error message.
        self.__db_path = os.path.normpath(db_path)
        database.set_path(self.__db_path)

        error_occurred = 0
        
        # Dispatch to the appropriate method.
        if self.__command == "create-tdb":
            return self.__ExecuteCreateTdb(db_path)
        
        method = {
            "create" : self.__ExecuteCreate,
            "create-target" : self.__ExecuteCreateTarget,
            "describe" : self.__ExecuteDescribe,
            "extensions" : self.__ExecuteExtensions,
            "gui" : self.__ExecuteServer,
            "ls" : self.__ExecuteList,
            "register" : self.__ExecuteRegister,
            "remote" : self.__ExecuteRemote,
            "run" : self.__ExecuteRun,
            "report" : self.__ExecuteReport,
            "summarize": self.__ExecuteSummarize,
            }[self.__command]

        return method()


    def GetDatabase(self):
        """Return the test database to use.

        returns -- The 'Database' to use for this execution.  Raises an
        exception if no 'Database' is available."""

        return database.get_database()


    def GetDatabaseIfAvailable(self):
        """Return the test database to use.

        returns -- The 'Database' to use for this execution, or 'None'
        if no 'Database' is available."""

        try:
            return self.GetDatabase()
        except:
            return None

    
    def GetTargetFileName(self):
        """Return the path to the file containing target specifications.

        returns -- The path to the file containing target specifications."""

        # See if the user requested a specific target file.
        target_file_name = self.GetCommandOption("targets")
        if target_file_name:
            return target_file_name
        # If there was no explicit option, use the "targets" file in the
        # database directory.
        return os.path.join(self.GetDatabase().GetConfigurationDirectory(),
                            self.target_file_name)
    

    def GetTargetsFromFile(self, file_name):
        """Return the 'Target's specified in 'file_name'.

        returns -- A list of the 'Target' objects specified in the
        target specification file 'file_name'."""

        try:
            document = qm.xmlutil.load_xml_file(file_name)
            targets_element = document.documentElement
            if targets_element.tagName != "targets":
                raise QMException, \
                      qm.error("could not load target file",
                               file = file_name)
            targets = []
            for node in targets_element.getElementsByTagName("extension"):
                # Parse the DOM node.
                target_class, arguments \
                    = (qm.extension.parse_dom_element
                       (node,
                        lambda n: get_extension_class(n, "target",
                                                      self.GetDatabase())))
                # Build the target.
                target = target_class(self.GetDatabase(), arguments)
                # Accumulate targets.
                targets.append(target)

            return targets
        except Context:
            raise QMException, \
                  qm.error("could not load target file",
                           file=file_name)

        
        
    def GetTargets(self):
        """Return the 'Target' objects specified by the user.

        returns -- A sequence of 'Target' objects."""

        if not test.get_targets():
            file_name = self.GetTargetFileName()
            if os.path.exists(file_name):
                test.set_targets(self.GetTargetsFromFile(file_name))
            else:
                # The target file does not exist.
                concurrency = self.GetCommandOption("concurrency")
                if concurrency is None:
                    # No concurrency specified.  Run single-threaded.
                    concurrency = 1
                else:
                    # Convert the concurrency to an integer.
                    try:
                        concurrency = int(concurrency)
                    except ValueError:
                        raise qm.cmdline.CommandError, \
                              qm.error("concurrency not integer",
                                       value=concurrency)
                # Construct the target.
                arguments = {}
                arguments["name"] = "local"
                arguments["group"] = "local"
                if concurrency > 1:
                    class_name = "thread_target.ThreadTarget"
                    arguments["threads"] = concurrency
                else:
                    class_name = "serial_target.SerialTarget"
                target_class = get_extension_class(class_name,
                                                   'target', self.GetDatabase())
                test.set_targets([target_class(self.GetDatabase(), arguments)])
            
        return test.get_targets()
        

    def GetTracer(self):
        """Return the 'Tracer' associated with this instance of QMTest.

        returns -- The 'Tracer' associated with this instance of QMTest."""

        return self.__tracer

    
    def MakeContext(self):
        """Construct a 'Context' object for running tests."""

        context = Context()

        # First, see if a context file was specified on the command
        # line.
        use_implicit_context_file = 1
        for option, argument in self.__command_options:
            if option == "load-context":
                use_implicit_context_file = 0
                break

        # If there is no context file, read the default context file.
        if (use_implicit_context_file
            and os.path.isfile(self.context_file_name)):
            context.Read(self.context_file_name)
                
        for option, argument in self.__command_options:
            # Look for the '--load-context' option.
            if option == "load-context":
                context.Read(argument)
            # Look for the '--context' option.
            elif option == "context":
                # Parse the argument.
                name, value = qm.common.parse_assignment(argument)
            
                try:
                    # Insert it into the context.
                    context[name] = value
                except ValueError, msg:
                    # The format of the context key is invalid, but
                    # raise a 'CommandError' instead.
                    raise qm.cmdline.CommandError, msg

        return context


    def GetExecutablePath(self):
        """Return the path to the QMTest executable.

        returns -- A string giving the path to the QMTest executable.
        This is the path that should be used to invoke QMTest
        recursively.  Returns 'None' if the path to the QMTest
        executable is uknown."""

        return self.__qmtest_path
    

    def GetFileResultStreamClass(self):
        """Return the 'ResultStream' class used for results files.

        returns -- The 'ResultStream' class used for results files."""

        return get_extension_class(self.__file_result_stream_class_name,
                                   "result_stream",
                                   self.GetDatabaseIfAvailable())

    def GetTextResultStreamClass(self):
        """Return the 'ResultStream' class used for textual feedback.

        returns -- the 'ResultStream' class used for textual
        feedback."""

        return get_extension_class(self.__text_result_stream_class_name,
                                   "result_stream",
                                   self.GetDatabaseIfAvailable())
        

    def __GetAttributeOptions(self, expect_value = True):
        """Return the attributes specified on the command line.

        'expect_value' -- True if the attribute is to be parsed as
        an assignment.

        returns -- A dictionary. If expect_value is True, it
        maps attribute names (strings) to values (strings).
        Else it contains the raw attribute strings, mapping to None.
        There is an entry for each attribute specified with
        '--attribute' on the command line."""

        # There are no attributes yet.
        attributes = {}

        # Go through the command line looking for attribute options.
        for option, argument in self.__command_options:
            if option == "attribute":
                if expect_value:
                    name, value = qm.common.parse_assignment(argument)
                    attributes[name] = value
                else:
                    attributes[argument] = None
        return attributes
    

    def __GetAnnotateOptions(self):
        """Return all annotate options.

        returns -- A dictionary containing the annotation name / value pairs."""

        annotations = {}
        for option, argument in self.__command_options:
            if option == "annotate":
                name, value = qm.common.parse_assignment(argument)
                annotations[name] = value
        return annotations
    

    def __ExecuteCreate(self):
        """Create a new extension file."""

        # Check that the right number of arguments are present.
        if len(self.__arguments) != 2:
            self.__WriteCommandHelp("create")
            return 2

        # Figure out what database (if any) we are using.
        database = self.GetDatabaseIfAvailable()
        
        # Get the extension kind.
        kind = self.__arguments[0]
        self.__CheckExtensionKind(kind)

        extension_id = self.GetCommandOption("id")
        if extension_id is not None:
            if not database:
                raise QMException, qm.error("no db specified")
            if not database.IsModifiable():
                raise QMException, qm.error("db not modifiable")
            extension_loader = database.GetExtension
        else:
            extension_loader = None

        class_loader = lambda n: get_extension_class(n, kind, database)
        
        # Process the descriptor.
        (extension_class, more_arguments) \
             = (qm.extension.parse_descriptor
                (self.__arguments[1], class_loader, extension_loader))

        # Validate the --attribute options.
        arguments = self.__GetAttributeOptions()
        arguments = qm.extension.validate_arguments(extension_class,
                                                    arguments)
        # Override the --attribute options with the arguments provided
        # as part of the descriptor.
        arguments.update(more_arguments)

        if extension_id is not None:
            # Create the extension instance.  Objects derived from
            # Runnable require magic additional arguments.
            if issubclass(extension_class, (Runnable, Suite)):
                extras = { extension_class.EXTRA_ID : extension_id, 
                           extension_class.EXTRA_DATABASE : database }
            else:
                extras = {}
            extension = extension_class(arguments, **extras)
            # Write the extension to the database.
            database.WriteExtension(extension_id, extension)
        else:
            # Figure out what file to use.
            filename = self.GetCommandOption("output")
            if filename is not None:
                file = open(filename, "w")
            else:
                file = sys.stdout
            # Write out the file.
            qm.extension.write_extension_file(extension_class, arguments,
                                              file)

        return 0
    
        
    def __ExecuteCreateTdb(self, db_path):
        """Handle the command for creating a new test database.

        'db_path' -- The path at which to create the new test database."""

        if len(self.__arguments) != 0:
            self.__WriteCommandHelp("create-tdb")
            return 2
        
        # Create the directory if it does not already exists.
        if not os.path.isdir(db_path):
            os.mkdir(db_path)
        # Create the configuration directory.
        config_dir = database.get_configuration_directory(db_path)
        if not os.path.isdir(config_dir):
            os.mkdir(config_dir)

        # Reformulate this command in terms of "qmtest create".  Start by
        # adding "--output ".
        self.__command_options.append(("output",
                                       database.get_configuration_file(db_path)))
        # Figure out what database class to use.
        class_name \
            = self.GetCommandOption("class", "xml_database.XMLDatabase")
        # Add the extension kind and descriptor.
        self.__arguments.append("database")
        self.__arguments.append(class_name)
        # Now process this just like "qmtest create".
        self.__ExecuteCreate()
        # Print a helpful message.
        self._stdout.write(qm.message("new db message", path=db_path) + "\n")

        return 0

    
    def __ExecuteCreateTarget(self):
        """Create a new target file."""

        # Make sure that the arguments are correct.
        if (len(self.__arguments) < 2 or len(self.__arguments) > 3):
            self.__WriteCommandHelp("create-target")
            return 2

        # Pull the required arguments out of the command line.
        target_name = self.__arguments[0]
        class_name = self.__arguments[1]
        if (len(self.__arguments) > 2):
            target_group = self.__arguments[2]
        else:
            target_group = ""

        # Load the database.
        database = self.GetDatabase()

        # Load the target class.
        target_class = get_extension_class(class_name, "target", database)

        # Get the dictionary of class arguments.
        field_dictionary \
            = qm.extension.get_class_arguments_as_dictionary(target_class)

        # Get the name of the target file.
        file_name = self.GetTargetFileName()
        # If the file already exists, read it in.
        if os.path.exists(file_name):
            # Load the document.
            document = qm.xmlutil.load_xml_file(file_name)
            # If there is a previous entry for this target, discard it.
            targets_element = document.documentElement
            duplicates = []
            for target_element \
                in targets_element.getElementsByTagName("extension"):
                for attribute \
                    in target_element.getElementsByTagName("argument"):
                    if attribute.getAttribute("name") == "name":
                        name = field_dictionary["name"].\
                               GetValueFromDomNode(attribute.childNodes[0],
                                                   None)
                        if name == target_name:
                            duplicates.append(target_element)
                            break
            for duplicate in duplicates:
                targets_element.removeChild(duplicate)
                duplicate.unlink()
        else:
            document = (qm.xmlutil.create_dom_document
                        (public_id = "QMTest/Target",
                         document_element_tag = "targets"))
            targets_element = document.documentElement
            
        # Get the attributes.
        attributes = self.__GetAttributeOptions()
        attributes["name"] = target_name
        attributes["group"] = target_group
        attributes = qm.extension.validate_arguments(target_class,
                                                     attributes)
        
        # Create the target element.
        target_element = qm.extension.make_dom_element(target_class,
                                                       attributes,
                                                       document)
        targets_element.appendChild(target_element)

        # Write out the XML file.
        document.writexml(open(self.GetTargetFileName(), "w"))
        
        return 0

    
    def __ExecuteExtensions(self):
        """List the available extension classes."""

        # Check that the right number of arguments are present.
        if len(self.__arguments) != 0:
            self.__WriteCommandHelp("extensions")
            return 2

        database = self.GetDatabaseIfAvailable()

        # Figure out what kinds of extensions we're going to list.
        kind = self.GetCommandOption("kind")
        if kind:
            self.__CheckExtensionKind(kind)
            kinds = [kind]
        else:
            kinds = base.extension_kinds

        for kind in kinds:
            # Get the available classes.
            names = qm.test.base.get_extension_class_names(kind,
                                                           database,
                                                           self.__db_path)
            # Build structured text describing the classes.
            description = "** Available %s classes **\n\n" % kind
            for n in names:
                description += "  * " + n + "\n\n    "
                # Try to load the class to get more information.
                try:
                    extension_class = get_extension_class(n, kind, database)
                    description \
                        += qm.extension.get_class_description(extension_class,
                                                              brief=1)
                except:
                    description += ("No description available: "
                                    "could not load class.")
                description += "\n\n"
                
            self._stdout.write(qm.structured_text.to_text(description))

        return 0
            

    def __ExecuteDescribe(self):
        """Describe an extension."""

        # Check that the right number of arguments are present.
        if len(self.__arguments) != 2:
            self.__WriteCommandHelp("describe")
            return 2

        kind = self.__arguments[0]
        long_format = self.GetCommandOption("long") != None

        database = self.GetDatabaseIfAvailable()
        class_ = get_extension_class(self.__arguments[1], kind, database)

        attributes = (self.__GetAttributeOptions(False)
                      or class_._argument_dictionary)

        print ""
        print "class name:", get_extension_class_name(class_)
        print "  ", get_class_description(class_, brief=not long_format)
        print ""
        print "class attributes:"
        tab = max([len(name) for name in attributes])
        for name in attributes:
            field = class_._argument_dictionary.get(name)
            if not field:
                self._stderr.write("Unknown attribute '%s'.\n"%name)
                return 2
            value = field.GetDefaultValue()
            description = field.GetDescription()
            if not long_format:
                description = qm.structured_text.get_first(description)
            print "   %-*s     %s"%(tab, name, description)


    def __ExecuteList(self):
        """List the contents of the database."""

        database = self.GetDatabase()

        long_format = self.HasCommandOption("long")
        details_format = self.HasCommandOption("details")
        recursive = self.HasCommandOption("recursive")

        # If no arguments are specified, list the root directory.
        args = self.__arguments or ("",)

        # Get all the extensions to list.
        extensions = {}
        for arg in args:
            extension = database.GetExtension(arg)
            if not extension:
                raise QMException, qm.error("no such ID", id = arg)
            if isinstance(extension, qm.test.suite.Suite):
                if recursive:
                    test_ids, suite_ids = extension.GetAllTestAndSuiteIds()
                    extensions.update([(i, database.GetExtension(i))
                                       for i in test_ids + suite_ids])
                else:
                    ids = extension.GetTestIds() + extension.GetSuiteIds()
                    extensions.update([(i, database.GetExtension(i))
                                       for i in ids])
            else:
                extensions[arg] = extension

        # Get the labels for the extensions, in alphabetical order.
        ids = extensions.keys()
        ids.sort()

        # In the short format, just print the labels.
        if not long_format:
            for id in ids:
                print >> sys.stdout, id
            return 0

        # In the long format, print three columns: the extension kind,
        # class name, and the label.  We make two passes over the
        # extensions so that the output will be tidy. In the first pass,
        # calculate the width required for the first two columns in the
        # output.  The actual output occurs in the second pass.
        longest_kind = 0
        longest_class = 0
        for i in (0, 1):
            for id in ids:
                extension = extensions[id]
                if isinstance(extension,
                              qm.test.directory_suite.DirectorySuite):
                    kind = "directory"
                    class_name = ""
                else:
                    kind = extension.__class__.kind
                    class_name = extension.GetClassName()
                    
                if i == 0:
                    kind_len = len(kind) + 1
                    if kind_len > longest_kind:
                        longest_kind = kind_len
                    class_len = len(class_name) + 1
                    if class_len > longest_class:
                        longest_class = class_len
                else:
                    print >> sys.stdout, \
                          "%-*s%-*s%s" % (longest_kind, kind,
                                          longest_class, class_name, id)
                    if details_format:
                        tab = max([len(name)
                                   for name in extension._argument_dictionary])
                        for name in extension._argument_dictionary:
                            value = str(getattr(extension, name))
                            print "   %-*s     %s"%(tab, name, value)

        return 0
        
        
    def __ExecuteRegister(self):
        """Register a new extension class."""

        # Make sure that the KIND and CLASS were specified.
        if (len(self.__arguments) != 2):
            self.__WriteCommandHelp("register")
            return 2
        kind = self.__arguments[0]
        class_name = self.__arguments[1]

        # Check that the KIND is valid.
        self.__CheckExtensionKind(kind)

        # Check that the CLASS_NAME is well-formed.
        if class_name.count('.') != 1:
            raise qm.cmdline.CommandError, \
                  qm.error("invalid class name",
                           class_name = class_name)
        module, name = class_name.split('.')

        # Try to load the database.  It may provide additional
        # directories to search.
        database = self.GetDatabaseIfAvailable()
        # Hunt through all of the extension class directories looking
        # for an appropriately named module.
        found = None
        directories = get_extension_directories(kind, database,
                                                self.__db_path)
        for directory in directories:
            for ext in (".py", ".pyc", ".pyo"):
                file_name = os.path.join(directory, module + ext)
                if os.path.exists(file_name):
                    found = file_name
                    break
            if found:
                break

        # If we could not find the module, issue an error message.
        if not found:
            raise qm.QMException, \
                  qm.error("module does not exist",
                           module = module)

        # Inform the user of the location in which QMTest found the
        # module.  (Sometimes, there might be another module with the
        # same name in the path.  Telling the user where we've found
        # the module will help the user to deal with this situation.)
        self._stdout.write(qm.structured_text.to_text
                           (qm.message("loading class",
                                       class_name = name,
                                       file_name = found)))
        
        # We have found the module.  Try loading it.
        extension_class = get_extension_class_from_directory(class_name,
                                                             kind,
                                                             directory,
                                                             directories)

        # Create or update the classes.qmc file.
        classes_file_name = os.path.join(directory, "classes.qmc")
        
        # Create a new DOM document for the class directory.
        document = (qm.xmlutil.create_dom_document
                    (public_id = "Class-Directory",
                     document_element_tag="class-directory"))
        
        # Copy entries from the old file to the new one.
        extensions = get_extension_class_names_in_directory(directory)
        for k, ns in extensions.iteritems():
            for n in ns:
                # Remove previous entries for the class being added.
                if k == kind and n == class_name:
                    continue
                element = document.createElement("class")
                element.setAttribute("kind", k)
                element.setAttribute("name", n)
                document.documentElement.appendChild(element)

        # Add an entry for the new element.
        element = document.createElement("class")
        element.setAttribute("kind", kind)
        element.setAttribute("name", class_name)
        document.documentElement.appendChild(element)        

        # Write out the file.
        document.writexml(open(classes_file_name, "w"),
                          addindent = " ", newl = "\n")

        return 0

        
    def __ExecuteSummarize(self):
        """Read in test run results and summarize."""

        # If no results file is specified, use a default value.
        if len(self.__arguments) == 0:
            results_path = self.results_file_name
        else:
            results_path = self.__arguments[0]

        database = self.GetDatabaseIfAvailable()

        # The remaining arguments, if any, are test and suite IDs.
        id_arguments = self.__arguments[1:]
        # Are there any?
        # '.' is an alias for , and thus shadows other selectors.
        if len(id_arguments) > 0 and not '.' in id_arguments:
            ids = set()
            # Expand arguments into test/resource IDs.
            if database:
                for id in id_arguments:
                    extension = database.GetExtension(id)
                    if not extension:
                        raise qm.cmdline.CommandError, \
                              qm.error("no such ID", id = id)
                    if extension.kind == database.SUITE:
                        ids.update(extension.GetAllTestAndSuiteIds()[0])
                    else:
                        ids.add(id)
            else:
                ids = set(id_arguments)
        else:
            # No IDs specified.  Show all test and resource results.
            # Don't show any results by test suite though.
            ids = None

        # Get an iterator over the results.
        try:
            results = base.load_results(results_path, database)
        except Exception, exception:
            raise QMException, \
                  qm.error("invalid results file",
                           path=results_path,
                           problem=str(exception))

        any_unexpected_outcomes = 0

        # Load expectations.
        expectations = (self.GetCommandOption('expectations') or
                        self.GetCommandOption('outcomes'))
        expectations = base.load_expectations(expectations,
                                              database,
                                              results.GetAnnotations())
        # Compute the list of result streams to which output should be
        # written.
        streams = self.__CreateResultStreams(self.GetCommandOption("output"),
                                             results.GetAnnotations(),
                                             expectations)

        resource_results = {}
        for r in results:
            if r.GetKind() != Result.TEST:
                if ids is None or r.GetId() in ids:
                    for s in streams:
                        s.WriteResult(r)
                elif r.GetKind() == Result.RESOURCE_SETUP:
                    resource_results[r.GetId()] = r
                continue
            # We now known that r is test result.  If it's not one
            # that interests us, we're done.
            if ids is not None and r.GetId() not in ids:
                continue
            # If we're filtering, and this test was not run because it
            # depended on a resource that was not set up, emit the
            # resource result here.
            if (ids is not None
                and r.GetOutcome() == Result.UNTESTED
                and r.has_key(Result.RESOURCE)):
                rid = r[Result.RESOURCE]
                rres = resource_results.get(rid)
                if rres:
                    del resource_results[rid]
                    for s in streams:
                        s.WriteResult(rres)
            # Write out the test result.             
            for s in streams:
                s.WriteResult(r)
                if (not any_unexpected_outcomes
                    and r.GetOutcome() != expectations.Lookup(r.GetId())):
                    any_unexpected_outcomes = 1
        # Shut down the streams.            
        for s in streams:
            s.Summarize()

        return any_unexpected_outcomes
        

    def __ExecuteRemote(self):
        """Execute the 'remote' command."""

        database = self.GetDatabase()

        # Get the target class.  For now, we always run in serial when
        # running remotely.
        target_class = get_extension_class("serial_target.SerialTarget",
                                           'target', database)
        # Build the target.
        target = target_class(database, { "name" : "child" })

        # Start the target.
        response_queue = Queue.Queue(0)
        target.Start(response_queue)
        
        # Read commands from standard input, and reply to standard
        # output.
        while 1:
            # Read the command.
            command = cPickle.load(sys.stdin)
            
            # If the command is just a string, it should be
            # the 'Stop' command.
            if isinstance(command, types.StringType):
                assert command == "Stop"
                target.Stop()
                break

            # Decompose command.
            method, id, context = command
            # Get the descriptor.
            descriptor = database.GetTest(id)
            # Run it.
            target.RunTest(descriptor, context)
            # There are no results yet.
            results = []
            # Read all of the results.
            while 1:
                try:
                    result = response_queue.get(0)
                    results.append(result)
                except Queue.Empty:
                    # There are no more results.
                    break
            # Pass the results back.
            cPickle.dump(results, sys.stdout)
            # The standard output stream is bufferred, but the master
            # will block waiting for a response, so we must flush
            # the buffer here.
            sys.stdout.flush()

        return 0


    def __ExecuteReport(self):
        """Execute a 'report' command."""

        output = self.GetCommandOption("output")
        flat = self.GetCommandOption("flat") != None

        # Check that at least one result file is present.
        if not output or len(self.__arguments) < 1:
            self.__WriteCommandHelp("report")
            return 2

        # If the database can be loaded, use it to find all
        # available tests. The default (non-flat) format requires a database.
        if flat:
            database = self.GetDatabaseIfAvailable()
        else:
            database = self.GetDatabase()

        report_generator = ReportGenerator(output, database)
        report_generator.GenerateReport(flat, self.__arguments)
        

    def __ExecuteRun(self):
        """Execute a 'run' command."""
        
        database = self.GetDatabase()

        # Handle the 'seed' option.  First create the random number
        # generator we will use.
        seed = self.GetCommandOption("seed")
        if seed:
            # A seed was specified.  It should be an integer.
            try:
                seed = int(seed)
            except ValueError:
                raise qm.cmdline.CommandError, \
                      qm.error("seed not integer", seed=seed)
            # Use the specified seed.
            random.seed(seed)

        # Figure out what tests to run.
        if len(self.__arguments) == 0:
            # No IDs specified; run the entire test database.
            self.__arguments.append("")
        elif '.' in self.__arguments:
            # '.' is an alias for , and thus shadows other selectors.
            self.__arguments = [""]

        # Expand arguments in test IDs.
        try:
            test_ids, test_suites \
                      = self.GetDatabase().ExpandIds(self.__arguments)
        except (qm.test.database.NoSuchTestError,
                qm.test.database.NoSuchSuiteError), exception:
            raise qm.cmdline.CommandError, str(exception)
        except ValueError, exception:
            raise qm.cmdline.CommandError, \
                  qm.error("no such ID", id=str(exception))

        # Handle the --annotate options.
        annotations = self.__GetAnnotateOptions()

        # Load expectations.
        expectations = (self.GetCommandOption('expectations') or
                        self.GetCommandOption('outcomes'))
        expectations = base.load_expectations(expectations,
                                              database,
                                              annotations)
        # Filter the set of tests to be run, eliminating any that should
        # be skipped.
        test_ids = self.__FilterTestsToRun(test_ids, expectations)
        
        # Figure out which targets to use.
        targets = self.GetTargets()
        # Compute the context in which the tests will be run.
        context = self.MakeContext()

        # Handle the --output option.
        if self.HasCommandOption("no-output"):
            # User specified no output.
            result_file_name = None
        else:
            result_file_name = self.GetCommandOption("output")
            if result_file_name is None:
                # By default, write results to a default file.
                result_file_name = self.results_file_name

        # Compute the list of result streams to which output should be
        # written.
        result_streams = self.__CreateResultStreams(result_file_name,
                                                    annotations,
                                                    expectations)

        if self.HasCommandOption("random"):
            # Randomize the order of the tests.
            random.shuffle(test_ids)
        else:
            test_ids.sort()

        # Run the tests.
        engine = ExecutionEngine(database, test_ids, context, targets,
                                 result_streams,
                                 expectations)
        if engine.Run():
            return 1

        return 0
                                                    

    def __ExecuteServer(self):
        """Process the server command."""

        database = self.GetDatabase()

        # Get the port number specified by a command option, if any.
        # Otherwise use a default value.
        port_number = self.GetCommandOption("port", default=0)
        try:
            port_number = int(port_number)
        except ValueError:
            raise qm.cmdline.CommandError, qm.error("bad port number")
        # Get the local address specified by a command option, if any.
        # If not was specified, use the loopback address.  The loopback
        # address is used by default for security reasons; it restricts
        # access to the QMTest server to users on the local machine.
        address = self.GetCommandOption("address", default="127.0.0.1")

        # If a log file was requested, open it now.
        log_file_path = self.GetCommandOption("log-file")
        if log_file_path == "-":
            # A hyphen path name means standard output.
            log_file = sys.stdout
        elif log_file_path is None:
            # No log file.
            log_file = None
        else:
            # Otherwise, it's a file name.  Open it for append.
            log_file = open(log_file_path, "a+")

        # If a PID file was requested, create it now.
        pid_file_path = self.GetCommandOption("pid-file")
        if pid_file_path is not None:
            # If a PID file was requested, but no explicit path was
            # given, use a default value.
            if not pid_file_path:
                pid_file_path = qm.common.rc.Get("pid-file",
                                                 "/var/run/qmtest.pid",
                                                 "qmtest")
            try:
                pid_file = open(pid_file_path, "w")
            except IOError, e:
                raise qm.cmdline.CommandError, str(e)
        else:
            pid_file = None
            
        # Create a run database, if requested.
        run_db = None
        directory = self.GetCommandOption("results", default="")
        if directory:
            directory = os.path.normpath(directory)
            run_db = DirRunDatabase(directory, database)

        # Load expectations. Only support the 'outcome' option here,
        # as 'expectations' in general are unsupported with this GUI.
        expectations = self.GetCommandOption('outcomes')
        expectations = base.load_expectations(expectations, database)
        # Make sure this is either an ExpectationDatabase or a
        # PreviousRun
        if not type(expectations) in (ExpectationDatabase, PreviousTestRun):
            raise qm.cmdline.CommandError, 'not a valid results file'
        # Figure out which targets to use.
        targets = self.GetTargets()
        # Compute the context in which the tests will be run.
        context = self.MakeContext()
        # Set up the server.
        server = QMTestServer(database,
                              port_number, address,
                              log_file, targets, context,
                              expectations,
                              run_db)
        port_number = server.GetServerAddress()[1]
        
        # Construct the URL to the main page on the server.
        if address == "":
            url_address = qm.platform.get_host_name()
        else:
            url_address = address
        if run_db:
            url = "http://%s:%d/report/dir" % (url_address, port_number)
        else:
            url = "http://%s:%d/test/dir" % (url_address, port_number)
            
        if not self.HasCommandOption("no-browser"):
            # Now that the server is bound to its address, start the
            # web browser.
            qm.platform.open_in_browser(url)
            
        message = qm.message("server url", url=url)
        sys.stderr.write(message + "\n")

        # Become a daemon, if appropriate.
        if self.GetCommandOption("daemon") is not None:
            # Fork twice.
            if os.fork() != 0:
                os._exit(0)
            if os.fork() != 0:
                os._exit(0)
            # This process is now the grandchild of the original
            # process.

        # Write out the PID file.  The correct PID is not known until
        # after the transformation to a daemon has taken place.
        try:
            if pid_file:
                pid_file.write(str(os.getpid()))
                pid_file.close()
                
            # Accept requests.
            try:
                server.Run()
            except qm.platform.SignalException, se:
                if se.GetSignalNumber() == signal.SIGTERM:
                    # If we receive SIGTERM, shut down.
                    pass
                else:
                    # Other signals propagate outwards.
                    raise
            except KeyboardInterrupt:
                # If we receive a keyboard interrupt (Ctrl-C), shut down.
                pass
        finally:
            if pid_file:
                os.remove(pid_file_path)
                
        return 0


    def __WriteCommandHelp(self, command):
        """Write out help information about 'command'.

        'command' -- The name of the command for which help information
        is required."""

        self._stderr.write(self.__parser.GetCommandHelp(command))

    def __FilterTestsToRun(self, test_ids, expectations):
        """Return those tests from 'test_ids' that should be run.

        'test_ids' -- A sequence of test ids.

        'expectations' -- An ExpectationDatabase.

        returns -- Those elements of 'test_names' that are not to be
        skipped.  If 'a' precedes 'b' in 'test_ids', and both 'a' and
        'b' are present in the result, 'a' will precede 'b' in the
        result."""

        # The --rerun option indicates that only failing tests should
        # be rerun.
        rerun_file_name = self.GetCommandOption("rerun")
        if rerun_file_name:
            # Load the outcomes from the file specified.
            outcomes = base.load_outcomes(rerun_file_name,
                                          self.GetDatabase())
            # Filter out tests that have unexpected outcomes.
            test_ids = [t for t in test_ids
                        if outcomes.get(t, Result.PASS)
                        != expectations.Lookup(t).GetOutcome()]
        
        return test_ids


    def __CheckExtensionKind(self, kind):
        """Check that 'kind' is a valid extension kind.

        'kind' -- A string giving the name of an extension kind.  If the
        'kind' does not name a valid extension kind, an appropriate
        exception is raised."""

        if kind not in base.extension_kinds:
            raise qm.cmdline.CommandError, \
                  qm.error("invalid extension kind",
                           kind = kind)

                       
    def __CreateResultStreams(self, output_file, annotations, expectations):
        """Return the result streams to use.

        'output_file' -- If not 'None', the name of a file to which
        the standard results file format should be written.

        'annotations' -- A dictionary with annotations for this test run.

        'expectations' -- An ExpectationDatabase.
        
        returns -- A list of 'ResultStream' objects, as indicated by the
        user."""

        database = self.GetDatabaseIfAvailable()

        result_streams = []

        arguments = {}
        arguments['expected_outcomes'] = expectations.GetExpectedOutcomes()

        # Look up the summary format.
        format = self.GetCommandOption("format", "")
        if format and format not in self.summary_formats:
            # Invalid format.  Complain.
            valid_format_string = string.join(
                map(lambda f: '"%s"' % f, self.summary_formats), ", ")
            raise qm.cmdline.CommandError, \
                  qm.error("invalid results format",
                           format=format,
                           valid_formats=valid_format_string)
        if format != "none":
            args = { "format" : format }
            args.update(arguments)
            stream = self.GetTextResultStreamClass()(args)
            result_streams.append(stream)

        f = lambda n: get_extension_class(n, "result_stream", database)
        
        # Look for all of the "--result-stream" options.
        for opt, opt_arg in self.__command_options:
            if opt == "result-stream":
                ec, args = qm.extension.parse_descriptor(opt_arg, f)
                args.update(arguments)
                result_streams.append(ec(args))

        # If there is an output file, create a standard results file on
        # that file.
        if output_file is not None:
            rs = (self.GetFileResultStreamClass()
                  ({ "filename" : output_file}))
            result_streams.append(rs)

        for name, value in annotations.iteritems():
            for rs in result_streams:
                rs.WriteAnnotation(name, value)

        return result_streams
    
########################################################################
# Functions
########################################################################

def get_qmtest():
    """Returns the global QMTest object.

    returns -- The 'QMTest' object that corresponds to the currently
    executing thread.

    At present, there is only one QMTest object per process.  In the
    future, however, there may be more than one.  Then, this function
    will return different values in different threads."""

    return _the_qmtest
    
########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/0000775000076400007640000000000011122067201015410 5ustar  stefanstefanqmtest-2.4.1/qm/test/classes/dejagnu_stream.py0000664000076400007640000003450211107032221020753 0ustar  stefanstefan########################################################################
#
# File:   dejagnu_stream.py
# Author: Mark Mitchell
# Date:   04/30/2003
#
# Contents:
#   DejaGNUStream
#
# Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

import cgi
from   dejagnu_test import DejaGNUTest
import qm.fields
from   qm.test.file_result_stream import FileResultStream
from   qm.test.result import Result
from   qm.test.file_result_reader import FileResultReader
import re

########################################################################
# Classes
########################################################################

class DejaGNUStream(FileResultStream):
    """A 'DejaGNUStream' formats its output like DejaGNU."""

    arguments = [
        qm.fields.BooleanField(
            name = "show_expected_outcomes",
            title = "Show Expected Outcomes",
            description = """True if expected outcomes should be displayed.

            By default, only information about unexpected outcomes is
            displayed.""",
            default_value = "false"
            )
        ]

    __summary_outcomes = [
        DejaGNUTest.PASS,
        DejaGNUTest.FAIL,
        DejaGNUTest.KFAIL,
        DejaGNUTest.KPASS,
        DejaGNUTest.XPASS,
        DejaGNUTest.XFAIL,
        DejaGNUTest.UNRESOLVED,
        DejaGNUTest.UNTESTED,
        DejaGNUTest.UNSUPPORTED
        ]
    """The outcomes for which summary output should be produced."""
    
    __outcome_descs = {
        DejaGNUTest.PASS: "expected passes",
        DejaGNUTest.FAIL: "unexpected failures",
        DejaGNUTest.KPASS: "unexpected successes",
        DejaGNUTest.KFAIL: "expected failures",
        DejaGNUTest.XPASS: "unexpected successes",
        DejaGNUTest.XFAIL: "expected failures",
        DejaGNUTest.UNRESOLVED: "unresolved testcases",
        DejaGNUTest.UNTESTED: "untested testcases",
        DejaGNUTest.UNSUPPORTED: "unsupported tests",
        }
    """A map from DejaGNU outcomes to descriptions.

    See 'init_testcounts' in the DejaGNU distribution for the code
    emulated by this table."""

    __expected_outcomes = (
        DejaGNUTest.PASS,
        DejaGNUTest.KFAIL,
        DejaGNUTest.XFAIL,
        DejaGNUTest.UNRESOLVED,
        DejaGNUTest.UNSUPPORTED,
        DejaGNUTest.UNTESTED
        )
    """The DejaGNU outcomes that are considered "expected" results.

    DejaGNU results with these outcomes are not displayed unless
    'show_expected_outcomes' is true."""

    def __init__(self, arguments = None, **args):

        super(DejaGNUStream, self).__init__(arguments, **args)
        self.__outcomes = {}
        for o in DejaGNUTest.dejagnu_outcomes:
            self.__outcomes[o] = 0
            
            
    def WriteResult(self, result):

        # Get the DejaGNU annotations in sorted order.
        keys = filter(lambda k: k.startswith(DejaGNUTest.RESULT_PREFIX),
                      result.keys())
        keys.sort(lambda k1, k2: cmp(int(k1[len(DejaGNUTest.RESULT_PREFIX):]),
                                     int(k2[len(DejaGNUTest.RESULT_PREFIX):])))
        has_error = 0
        for k in keys:
            r = result[k]
            outcome = r[:r.find(":")]
            if (self.show_expected_outcomes == "true"
                or outcome not in self.__expected_outcomes):
                self.file.write(r + "\n")
            # Keep track of the outcomes.
            self.__outcomes[outcome] += 1
            if outcome == DejaGNUTest.ERROR:
                has_error = 1

        # If something went wrong running the test, emit an ERROR
        # message even if DejaGNU would not have.  These cases usually
        # indicate problems with the DejaGNU test itself.
        if not has_error and result.GetOutcome () == result.ERROR:
            self.file.write("ERROR: %s (%s)\n"
                            % (result.GetId(), result.GetCause()))
            self.__outcomes[DejaGNUTest.ERROR] += 1


    def Summarize(self):

        self.file.write("\n\t\t=== Summary ===\n\n")
        # This function emulates log_summary from the DejaGNU
        # distribution.
        for o in self.__summary_outcomes:
            if self.__outcomes[o]:
                desc = "# of %s" % self.__outcome_descs[o]
                self.file.write(desc)
                if len(desc) < 24:
                    self.file.write("\t")
                self.file.write("\t%d\n" % self.__outcomes[o])



class DejaGNUReader(FileResultReader):
    """A 'DejaGNUReader' reads a DejaGNU log file.

    The DejaGNU log file may then be processed by QMTest.  For
    example, QMTest may generate results in an alternative format, or
    display them in the QMTest GUI.  Therefore, this reader may be
    used to obtain the benefits of QMTest's reporting characteristics,
    when using a legacy DejaGNU testsuite.

    Unfortunately, DejaGNU log files are relativley unstructured.
    Therefore, this result reader uses heuristics that may not always
    be 100% robust.  Therefore, for optimal behavior, DejaGNU
    testsuites should be converted to QMTest testsuites."""

    arguments = [
        qm.fields.BooleanField(
            name = "is_combined",
            title = "Combined Format?",
            description=\
            """True if multiple results for the same test should be combined.

            DejaGNU will sometimes print multiple results for the same
            test.  For example, when testing a compiler, DejaGNU may
            issue one result indicating whether or not a file was
            successfully compiled and another result indicating
            whether or not the file was successfully executed.  When
            using the combined format, these two results will be treated as
            subparts of a single test.  When not using the combined
            format, these results will be treated as separate
            tests.

            The combined format is the default.  However, if you want
            to see statistics that precisely match DejaGNU, you should
            not use the combined format.""",
            default_value="true",
            ),
        qm.fields.BooleanField(
            name = "expectations",
            title = "GenerateExpectations?",
            description=\
            """True if expected (not actual) results should be generated.

            In this mode, the actual results will be ignored.
            Instead, a results file indicated expected failures as
            actual failures will be generated.""",
            default_value="false",
            ),
        ]
            
    __id_regexp = re.compile("^[^:]*:[\\s]*(?P[^\\s]*)")
    """A regular expression for determining test names.

    When applied to an outcome line from DejaGNU, this regular
    expression's 'id' field gives the name of the test, in the
    combined mode."""
    
    __cause_regexp = re.compile("\\((?P.*)\\)\\s*$")
    """A regular expression for determining failure causes.

    When applied to an outcome line from DejaGNU, this regular
    expression's 'cause' field gives the cause of the failure."""
    
    def __init__(self, arguments = None, **args):

        # Initialize the base class.
        super(DejaGNUReader, self).__init__(arguments, **args)
        # DejaGNU files start with "Test Run".
        if self.file.read(len("Test Run")) != "Test Run":
            raise FileResultReader.InvalidFile, \
                  "file is not a DejaGNU result stream"
        self.file.seek(0)
        if self.__UseCombinedMode():
            test_id, dejagnu_outcome, cause = self.__NextOutcome()
            if test_id:
                self.__next_result = Result(Result.TEST, test_id)
                self.__UpdateResult(self.__next_result,
                                    dejagnu_outcome,
                                    cause)


    def GetResult(self):

        if self.__UseCombinedMode():
            result = self.__next_result
            if not result:
                return None
            self.__next_result = None
        else:
            result = None
        while True:
            test_id, dejagnu_outcome, cause = self.__NextOutcome()
            # If there are no more results, stop.
            if not test_id:
                break
            if self.__UseCombinedMode() and test_id != result.GetId():
                self.__next_result = Result(Result.TEST, test_id)
                self.__UpdateResult(self.__next_result,
                                    dejagnu_outcome,
                                    cause)
                break
            elif not self.__UseCombinedMode():
                result = Result(Result.TEST, test_id)
            self.__UpdateResult(result, dejagnu_outcome, cause)
            if not self.__UseCombinedMode():
                break
        return result


    def __NextOutcome(self):
        """The next DejaGNU outcome in the file.

        returns -- A triplet ('test_id', 'outcome', 'cause').  The
        'test_id' is the name of the test.  The 'outcome' is the
        DejaGNU outcome (one of the 'DejaGNUTest.dejagnu_outcomes').
        The 'cause' is a string giving the cause (if known) of
        failure, if the test did not pass."""

        # Assume that there are no more results in the file.
        dejagnu_outcome = None
        # Scan ahead until we find a line that gives data about the
        # next result.
        while self.file:
            # Read the next line of the file.
            line = self.file.next()
            # Each test result is printed on a line by itself,
            # beginning with the DejaGNU outcome.  For example:
            #   PASS: g++.dg/compat/eh/template1 cp_compat_y_tst.o compile
            dejagnu_outcome = None
            for o in DejaGNUTest.dejagnu_outcomes:
                # Ignore WARNING and ERROR; those are not really test
                # results. 
                if (o not in (DejaGNUTest.WARNING,
                              DejaGNUTest.ERROR)
                    and line.startswith(o)):
                    o_len = len(o)
                    if line[o_len:o_len + 2] == ": ":
                        dejagnu_outcome = o
                    break
            if dejagnu_outcome:
                break
        # If we could not find any more result lines, then we have
        # read all of the results in the file.
        if not dejagnu_outcome:
            return None, None, None
        # Extract the name of the test.
        if self.__UseCombinedMode():
            match = self.__id_regexp.search(line)
            test_id = match.group("id")
        else:
            test_id = line[len(dejagnu_outcome) + 2:].strip()
        # Extract the cause of faiulre.
        cause = None
        if "execution test" in line:
            cause = "Compiled program behaved incorrectly."
        elif dejagnu_outcome == DejaGNUTest.UNSUPPORTED:
            cause = "Test is not applicable on this platform."
        elif self.__UseCombinedMode():
            match = self.__cause_regexp.search(line)
            if match:
                cause = match.group("cause").capitalize()
                if cause and cause[-1] != ".":
                    cause += "."
        else:
            cause = ""
        return test_id, dejagnu_outcome, cause
        
    
    def __UpdateResult(self, result, dejagnu_outcome, cause):
        """Update 'result' as indicated.

        'result' -- A 'Result', which may contain information from
        previous DejaGNU tests, in the combined mode.

        'dejagnu_outcome' -- The DejaGNU outcome (one of the
        'DejaGNUTest.dejagnu_outcomes') that applies to this
        'result'.

        'cause' -- The cause of failure, if known.

        The 'result' is modified to reflect the new outcome and
        cause.  Results can only get worse, in the sense that if
        reuslt has an outcome of 'Result.FAIL' upon entry to this
        return, it will never have an outcome of 'Result.PASS' upon
        return."""
                       
        # Translate the DejaGNU outcome into a QMTest outcome.
        if self.__GenerateExpectations():
            if dejagnu_outcome in (DejaGNUTest.KFAIL,
                                   DejaGNUTest.KPASS,
                                   DejaGNUTest.XFAIL,
                                   DejaGNUTest.XPASS):
                qmtest_outcome = Result.FAIL
            elif dejagnu_outcome in (DejaGNUTest.UNSUPPORTED,
                                     DejaGNUTest.UNRESOLVED):
                qmtest_outcome = Result.UNTESTED
            else:
                qmtest_outcome = Result.PASS
        else:
            qmtest_outcome = DejaGNUTest.outcome_map[dejagnu_outcome]
        # Update the QMTest result for this test, based on the
        # DejaGNU result.
        if qmtest_outcome == Result.ERROR:
            result.SetOutcome(Result.ERROR)
        elif (qmtest_outcome == Result.UNTESTED
              and result.GetOutcome() != Result.ERROR):
            result.SetOutcome(Result.UNTESTED)
        elif (qmtest_outcome == Result.FAIL
              and result.GetOutcome() not in (Result.ERROR,
                                              Result.UNTESTED)):
            result.SetOutcome(Result.FAIL)
        if qmtest_outcome != Result.PASS and cause:
            old_cause = result.GetCause()
            if old_cause and cause in old_cause:
                # Don't repeat the same cause multiple times.
                pass
            else:
                if old_cause:
                    old_cause += "  "
                old_cause += cgi.escape(cause)
                result.SetCause(old_cause)


    def __UseCombinedMode(self):
        """Returns true in the combined mode.

        returns -- True iff results should be read in the combined
        mode."""

        return self.is_combined == "true"


    def __GenerateExpectations(self):
        """Returns true if expected results should be generated.

        returns -- True iff the results generated should reflect
        expectations, rather than actual results."""

        return self.expectations == "true"

########################################################################
# Miscellaneous
########################################################################

__all__ = ["DejaGNUStream", "DejaGNUReader"]
qmtest-2.4.1/qm/test/classes/serial_target.py0000664000076400007640000000266411107032221020614 0ustar  stefanstefan########################################################################
#
# File:   serial_target.py
# Author: Mark Mitchell
# Date:   12/19/2001
#
# Contents:
#   SerialTarget
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
########################################################################

from   qm.test.target import Target
from   qm.temporary_directory import TemporaryDirectory

########################################################################
# Classes
########################################################################

class SerialTarget(Target):
    """A target that runs tests in serial on the local machine."""

    def __init__(self, database, properties):

        super(SerialTarget, self).__init__(database, properties)
        self.__temporary_directory = TemporaryDirectory()

            
    def IsIdle(self):
        """Return true if the target is idle.

        returns -- True if the target is idle.  If the target is idle,
        additional tasks may be assigned to it."""

        # The target is always idle when this method is called since
        # whenever it asked to perform a task it blocks the caller.
        return 1


    def _GetTemporaryDirectory(self):

        return self.__temporary_directory.GetPath()
qmtest-2.4.1/qm/test/classes/compilation_test.py0000664000076400007640000001310711107032221021336 0ustar  stefanstefan########################################################################
#
# File:   compilation_test.py
# Author: Stefan Seefeld
# Date:   2005-10-17
#
# Contents:
#   CompilationTest
#   CompiledResource
#   ExecutableTest
#
# Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

from compiler_test import CompilationStep, CompilerTest
from   qm.fields import *
from   qm.test.database import get_database
from   qm.test.result import *
from   qm.test.test import *
from   qm.test.resource import *
import qm.executable
from   qm.extension import parse_descriptor
from   qm.test.base import get_extension_class
from   compiler import Compiler
from   local_host import LocalHost


def _get_host(context, variable):
    """Get a host instance according to a particular context variable.
    Return a default 'LocalHost' host if the variable is undefined.

    'context' -- The context to read the host descriptor from.

    'variable' -- The name to which the host descriptor is bound.

    returns -- A Host instance.

    """

    target_desc = context.get(variable)
    if target_desc is None:
        target = LocalHost({})
    else:
        f = lambda n: get_extension_class(n, "host", get_database())
        host_class, arguments = parse_descriptor(target_desc.strip(), f)
        target = host_class(arguments)
    return target


########################################################################
# Classes
########################################################################

class CompilationTest(CompilerTest):
    """A CompilationTest compiles and optionally runs an executable.
    CompilationTest allows simple cross-testing. To run the executable on
    anything other than localhost, specify a Host descriptor by means of the
    context variable 'CompilationTest.target'."""

    options = SetField(TextField(description="""Test-specific options to pass to the compiler."""))
    ldflags = SetField(TextField(description="""Test-specific link flags to pass to the compiler."""))
    source_files = SetField(TextField(description="Source files to be compiled."))
    executable = TextField(description="The name of the executable to be compiled.")
    execute = BooleanField(default_value = True,
        description="Whether or not to run the compiled executable.")
    

    def Run(self, context, result):

        self._MakeDirectory(context)
        CompilerTest.Run(self, context, result)
        if self.execute:
            self._RemoveDirectory(context, result)


    def _GetCompiler(self, context):
        """The name of the compiler executable is taken from the context variable
        'CompilationTest.compiler_path'."""

        name = context["CompilationTest.compiler_path"]
        options = context.GetStringList("CompilationTest.compiler_options", [])
        ldflags = context.GetStringList("CompilationTest.compiler_ldflags", [])
        return Compiler(name, options, ldflags)


    def _GetCompilationSteps(self, context):

        # Compile the executable in a single step so we can apply all
        # options at once.
        return [CompilationStep(self._GetCompiler(context),
                                Compiler.MODE_LINK, self.source_files,
                                self.options, self.ldflags, self.executable, [])]


    def _IsExecutionRequired(self):

        return self.execute


    def _GetTarget(self, context):

        return _get_host(context, "CompilationTest.target")
        

    def _CheckOutput(self, context, result, prefix, output, diagnostics):

        if output:
            result[prefix + "output"] = result.Quote(output)

        return True


class CompiledResource(Resource):
    """A CompiledResource compiles an executable."""

    options = SetField(TextField(description="Resource-specific options to pass to the compiler."))
    source_files = SetField(TextField(description="Source files to be compiled."))
    executable = TextField(description="The name of the executable to be compiled.")


    def SetUp(self, context, result):

        self._context = context
        self._compiler = CompilationTest({'options':self.options,
                                          'source_files':self.source_files,
                                          'executable':self.executable,
                                          'execute':False},
                                         qmtest_id = self.GetId(),
                                         qmtest_database = self.GetDatabase())
        
        self._compiler.Run(context, result)
        directory = self._compiler._GetDirectory(context)
        self._executable = os.path.join(directory, self.executable)
        context['CompiledResource.executable'] = self._executable
        

    def CleanUp(self, result):

        self._compiler._RemoveDirectory(self._context, result)


class ExecutableTest(Test):
    """An ExecuableTest runs an executable from a CompiledResource.
    ExecutableTest allows simple cross-testing. To run the executable on
    anything other than localhost, specify a Host descriptor by means of the
    context variable 'ExecutableTest.host'."""

    args = SetField(TextField(description="Arguments to pass to the executable."))

    def Run(self, context, result):

        executable = context['CompiledResource.executable']
        host = _get_host(context, 'ExecutableTest.host')
        status, output = host.UploadAndRun(executable, self.args)
        if not result.CheckExitStatus('ExecutableTest.', 'Program', status):
            result.Fail('Unexpected exit_code')        

qmtest-2.4.1/qm/test/classes/compiler.py0000664000076400007640000004752511107032221017606 0ustar  stefanstefan########################################################################
#
# File:   compiler.py
# Author: Mark Mitchell
# Date:   12/11/2001
#
# Contents:
#   Compiler
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

"""Uniform interface to compilers.

This module contains the 'Compiler' class which is an abstract base
class providing a uniform interface to various compilers, such as the
GNU Compiler Collection and the Edison Design Group compilers."""

########################################################################
# Imports
########################################################################

from   qm.executable import *
import os
import os.path
import qm
import StringIO
import re
import sys
if sys.platform != "win32":
    import resource

########################################################################
# Classes
########################################################################

class CompilerExecutable(RedirectedExecutable):
    """A 'CompilerExecutable' is a 'Compiler' that is being run."""

    def _InitializeChild(self):
        """Initialize the child process.

        After 'fork' is called this method is invoked to give the
        child a chance to initialize itself.  '_InitializeParent' will
        already have been called in the parent process."""

        # Disable compiler core dumps.
        if sys.platform != "win32":
            resource.setrlimit(resource.RLIMIT_CORE, (0, 0))
        # Do whatever the base class version would otherwise do.
        RedirectedExecutable._InitializeChild(self)


    def _StdinPipe(self):
        """Return a pipe to which to redirect the standard input.

        returns -- A pipe, or 'None' if the standard input should be
        closed in the child."""

        # The compiler should not need the standard input.
        return None


    def _StderrPipe(self):
        """Return a pipe to which to redirect the standard input.

        returns -- A pipe, or 'None'.  If 'None' is returned, but
        '_StdoutPipe' returns a pipe, then the standard error and
        standard output will both be redirected to that pipe.  However,
        if '_StdoutPipe' also returns 'None', then the standard error
        will be closed in the child."""

        # The standard output and standard error are combined.
        return None



class Compiler:
    """A 'Compiler' compiles and links source files."""

    MODE_PREPROCESS = 'preprocess'
    """Preprocess the source files, but do not compile them."""
    
    MODE_COMPILE = 'compile'
    """Compile the source files, but do not assemble them."""
    
    MODE_ASSEMBLE = 'assemble'
    """Compile the source files, but do not link them."""

    MODE_LINK = 'link'
    """Compile and link the source files."""
    
    modes = [ MODE_COMPILE, MODE_ASSEMBLE, MODE_LINK, MODE_PREPROCESS ]
    """The available compilation modes."""

    def __init__(self, path, options=None, ldflags=None):
        """Construct a new 'Compiler'.

        'path' -- A string giving the location of the compiler
        executable.

        'options' -- A list of strings indicating options to the
        compiler, or 'None' if there are no options.

        'ldflags' -- A list of strings indicating ld flags to the
        compiler, or 'None' if there are no flags."""

        self._path = path
        self.SetOptions(options or [])
        self.SetLDFlags(ldflags or [])
            

    def Compile(self, mode, files, dir, options = [], ldflags = [],
                output = None, timeout = -1):
        """Compile the 'files'.
        
        'mode' -- The compilation mode (one of the 'Compiler.modes')
        that should be used to compile the 'files'.

        'files' -- A sequence of strings giving the names of source
        files (including, in general, assembly files, object files,
        and libraries) that should be compiled.

        'dir' -- The directory in which to run the compiler.
        
        'options' -- A sequence of strings indicating additional
        options that should be provided to the compiler.

        'ldflags' -- A sequence of strings indicating additional
        linker flags that should be provided to the compiler, if
        linking is done.

        'output' -- The name of the file should be created by the
        compilation.  If 'None', the compiler will use a default
        value.

        'timeout' -- The maximum number of seconds the compiler is
        permitted to run.  If 'timeout' is -1, the compiler is
        permitted to run forever.

        returns -- A tuple '(status, output)'.  The 'status' is the
        exit status returned by the compiler, as indicated by
        'waitpid'.  The 'output' is a string containing the standard
        outpt and standard errror generated by the compiler."""

        # Get the command to use.
        command = self.GetCompilationCommand(mode, files, options,
                                             ldflags, output)
        # Invoke the compiler.
        return self.ExecuteCommand(dir, command, timeout)
        

    def ExecuteCommand(self, dir, command, timeout = -1):
        """Execute 'command' in 'dir'.

        'dir' -- The directory in which to execute the command.
        
        'command' --  A sequence of strings, as returned by
        'GetCompilationCommand'.

        'timeout' -- The maximum number of seconds the compiler is
        permitted to run.  If 'timeout' is -1, the compiler is
        permitted to run forever.

        returns -- A tuple '(status, output)'.  The 'status' is the
        exit status returned by the compiler, as indicated by
        'waitpid'.  The 'output' is a string containing the standard
        output and standard errror generated by the compiler."""

        # Invoke the compiler.
        executable = CompilerExecutable(timeout)
        status = executable.Run(command, dir = dir)
        # Return all of the information.
        return (status, executable.stdout)

        
    def GetCompilationCommand(self, mode, files, options=[],
                              ldflags = [], output=None):
        """Return the appropriate command for compiling 'files'.

        'mode' -- The compilation mode (one of the 'Compiler.modes')
        that should be used to compile the 'files'.

        'files' -- A sequence of strings giving the names of source
        files (including, in general, assembly files, object files,
        and libraries) that should be compiled.

        'options' -- A sequence of strings indicating additional
        options that should be provided to the compiler.

        'ldflags' -- A sequence of strings indicating additional
        linker flags that should be provided to the compiler, if
        linking is done.

        'output' -- The name of the file should be created by the
        compilation.  If 'None', the compiler will use a default
        value.  (In some cases there may be multiple outputs.  For
        example, when generating multiple object files from multiple
        source files, the compiler will create a variety of objects.)

        returns -- A sequence of strings indicating the arguments,
        including 'argv[0]', for the compilation command."""

        # Start with the path to the compiler.
        command = [self.GetPath()]
        # Add switches indicating the compilation mode, if appropriate.
        command += self._GetModeSwitches(mode)
        # Add the options that should be used with every compilation.
        command += self._options
        # Add the options that apply to this compilation.
        command += options
        # Set the output file.
        if output:
            command += ["-o", output]
        # Add the input files.
        command += files
        if mode == Compiler.MODE_LINK:
            command += ldflags
            command += self.GetLDFlags()

        return command
        

    def ParseOutput(self, output, ignore_regexps = ()):
        """Turn the 'output' into a sqeuence of 'Diagnostic's.

        'output' -- A string containing the compiler's output.

        'ignore_regexps' -- A sequence of regular expressions.  If a
        diagnostic message matches one of these regular expressions,
        it will be ignored.

        returns -- A list of 'Diagnostic's corresponding to the
        messages indicated in 'output', in the order that they were
        emitted."""

        raise NotImplementedError
        
        
    def GetPath(self):
        """Return the location of the executable.

        returns -- A string giving the location of the executable.
        This location is the one that was specified as the 'path'
        argument to '__init__'."""
        
        return self._path


    def GetOptions(self):
        """Return the list of compilation options.

        returns -- A list of strings giving the compilation options
        specified when the 'Compiler' was constructed."""

        return self._options


    def SetOptions(self, options):
        """Reset the list of compiler options.
        
        'options' -- A list of strings indicating options to the
        compiler, or 'None' if there are no options."""

        self._options = options

        
    def GetLDFlags(self):
        """Return the list of link options.

        returns -- A list of strings giving the link options
        specified when the 'Compiler' was constructed."""

        return self._ldflags


    def SetLDFlags(self, ldflags):
        """Reset the list of link options.
        
        'ldflags' -- A list of strings indicating options to the
        linker, or 'None' if there are no flags."""

        self._ldflags = ldflags


    def GetExecutableExtension(self):
        """Return the extension for executables.

        returns -- The extension (including leading '.', if
        applicable) for executable files created by this compiler."""

        if sys.platform == "win32":
            return ".exe"
        else:
            return ""

        
    def GetObjectExtension(self):
        """Return the extension for object files.

        returns -- The extension (including leading '.', if
        applicable) for object files created by this compiler."""

        if sys.platform == "win32":
            return ".obj"
        else:
            return ".o"
        
    
    def _GetModeSwitches(self, mode):
        """Return the compilation switches for the compilation 'mode'.

        'mode' -- The compilation mode (one of 'Compiler.modes').

        returns -- A sequence of strings indicating the switches that
        are used to indicate the compilation mode."""

        if mode == self.MODE_PREPROCESS:
            return ["-E"]
        elif mode == self.MODE_COMPILE:
            return ["-S"]
        elif mode == self.MODE_ASSEMBLE:
            return ["-c"]
            
        # Other modes require no special option.
        return []
            
        

class SourcePosition:
    """A 'SourcePosition' indicates a location in source code.

    A 'SourcePosition' consists of:

    - A file name.  The file name is a string.  It may be an absolute
      or relative path.  If no file name is available, the file name
      is the empty string.

    - A line number, indexed from one.  If no line number is
      available, the line number is zero.

    - A column number, indexed from one.  If no column number is
      available, the column nubmer is zero."""

    def __init__(self, file, line, column):
        """Construct a new 'SourcePosition'.

        'file' -- The file name.

        'line' -- The line number, indexed from one.  If no line numer
        is availble, use zero for this parameter.

        'column' -- The column number, indexed from one.  If no column
        number is available, use zero for this parameter."""

        self.file = file
        self.line = line
        self.column = column

        
    def __str__(self):
        """Return a textual representation of this 'SourcePosition'.

        returns -- A string representing this 'SourcePosition'"""

        result = ''
        if self.file:
            result = result + '"%s"' % os.path.split(self.file)[0]
        if self.line:
            if self.file:
                result = result + ', '
            result = result + 'line %d' % self.line
        if self.column:
            result = result + ': %d' % self.column

        return result

    
        
class Diagnostic:
    """A 'Diagnostic' is a message issued by a compiler.

    Each 'Diagnostic' has the following attributes:

    - The source position that the compiler associates with the
      diagnostic.

    - The severity of the diagnostic.
    
    - The message issued by the compiler.

    A 'Diagnostic' may either be an actual diagnostic emitted by a
    compiler, or it may be the pattern for a diagnostic that might be
    emitted.  In the latter case, the message is a regular expression
    indicating the message that should be emitted."""

    def __init__(self, source_position, severity, message):
        """Construct a new 'Diagnostic'.

        'source_position' -- A 'SourcePosition' indicating where the
        diagnostic was issued.  For an expected diagnostic, 'None'
        indicates that the position does not matter.

        'severity' -- A string indicating the severity of the
        diagnostic.  For an expected diagnostic, 'None' indicates
        that the severity does not matter.

        'message' -- For an emitted diagnostic, a string indicating
        the message produced by the compiler.  For an expected
        diagnostic, a string giving a regular expression indicating
        the message that might be emitted.  For an expected
        diagnostic, 'None' indicates that the message does not
        matter."""

        self.source_position = source_position
        self.severity = severity
        self.message = message


    def __str__(self):
        """Return an informal representation of this 'Diagnostic'.

        returns -- A string representing this 'Diagnostic'."""

        if self.source_position:
            source_position_string = str(self.source_position)
        else:
            source_position_string = ""

        if self.severity:
            severity_string = self.severity
        else:
            severity_string = ""

        if self.message:
            message_string = self.message
        else:
            message_string = ""

        return '%s: %s: %s' % (source_position_string,
                               severity_string,
                               message_string)


########################################################################
# Compilers
########################################################################
    
class GCC(Compiler):
    """A 'GCC' is a GNU Compiler Collection compiler."""

    _severities = [ 'warning', 'error' ]
    """The diagnostic severities generated by the compiler.  Order
    matters; the order given here is the order that the
    '_severity_regexps' will be tried."""

    _severity_regexps = {
        'warning' :
          re.compile('^(?P[^:]*):((?P[^:]*):)?'
                     '(\s*(?P[0-9]+):)? '
                     'warning: (?P.*)$'),
        'error':
          re.compile('^(?P[^:]*):((?P[^:]*):)?'
                     '(\s*(?P[0-9]+):)? '
                     '(?P.*)$')
        }
    """A map from severities to compiled regular expressions.  If the
    regular expression matches a line in the compiler output, then that
    line indicates a diagnostic with the indicated severity."""

    _internal_error_regexp = re.compile('Internal (compiler )?error')
    """A compiled regular expression.  When an error message is matched
    by this regular expression, the error message indicates an
    internal error in the compiler."""

    MODE_PRECOMPILE = "precompile"
    """Precompile a header file."""

    modes = Compiler.modes + [MODE_PRECOMPILE]
    
    def ParseOutput(self, output, ignore_regexps = ()):
        """Return the 'Diagnostic's indicated in the 'output'.

        'output' -- A string giving the output from the compiler.

        'ignore_regexps' -- A sequence of regular expressions.  If a
        diagnostic message matches one of these regular expressions,
        it will be ignored.
        
        returns -- A list of 'Diagnostic's corresponding to the
        messages indicated in 'output', in the order that they were
        emitted."""

        # Assume there were no diagnostics.
        diagnostics = []
        # Create a file object containing the 'output'.
        f = StringIO.StringIO(output)
        # Reall all of the output, line by line.
        for line in f.readlines():
            for severity in self._severities:
                match = self._severity_regexps[severity].match(line)
                # If it does not look like an error message, skip it.
                if not match:
                    continue

                # Some error messages are ignored.
                ignore = 0
                for ignore_regexp in ignore_regexps:
                    if ignore_regexp.match(match.group()):
                        ignore = 1
                        break
                if ignore:
                    continue

                # An internal error is an error that indicates that
                # the compiler crashed.
                message = match.group('message')
                if (severity == 'error'
                    and self._internal_error_regexp.search(message)):
                    severity = 'internal_error'

                # If there is no line number, then we will not be
                # able to convert it to an integer.
                try:
                    line_number = int(match.group('line'))
                except:
                    line_number = 0

                # See if there is a column number.
                try:
                    column_number = int(match.group('column'))
                except:
                    column_number = 0

                source_position = SourcePosition(match.group('file'),
                                                 line_number,
                                                 column_number)
                diagnostic = Diagnostic(source_position,
                                        severity,
                                        message)
                diagnostics.append(diagnostic)
                break

        return diagnostics



class EDG(Compiler):
    """An 'EDG' is an Edison Design Group compiler."""

    __diagnostic_regexp = re.compile('^"(?P.*)", line (?P.*): '
                                     '(?P.*): (?P.*)$')
    
    def ParseOutput(self, output, ignore_regexps = ()):
        """Return the 'Diagnostic's indicated in the 'output'.

        'output' -- A string giving the output from the compiler.

        'ignore_regexps' -- A sequence of regular expressions.  If a
        diagnostic message matches one of these regular expressions,
        it will be ignored.
        
        returns -- A list of 'Diagnostic's corresponding to the
        messages indicated in 'output', in the order that they were
        emitted."""

        # Assume there were no diagnostics.
        diagnostics = []
        # Create a file object containing the 'output'.
        f = StringIO.StringIO(output)
        # Reall all of the output, line by line.
        for line in f.readlines():
            match = self.__diagnostic_regexp.match(line)
            if match:
                source_position = SourcePosition(match.group('file'),
                                                 int(match.group('line')),
                                                 0)
                diagnostic = Diagnostic(source_position,
                                        match.group('severity'),
                                        match.group('message'))
                diagnostics.append(diagnostic)


        return diagnostics
qmtest-2.4.1/qm/test/classes/python.py0000664000076400007640000003015711107032221017306 0ustar  stefanstefan########################################################################
#
# File:   python.py
# Author: Alex Samuel
# Date:   2001-04-03
#
# Contents:
#   Test classes for tests written in Python.
#
# Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

"""Test classes for tests written in Python."""

########################################################################
# imports
########################################################################

import qm
import qm.fields
import qm.test.base
from   qm.test.result import *
from   qm.test.test import *
import string
import sys
import types

########################################################################
# classes
########################################################################

class ExecTest(Test):
    """Check that a Python expression evaluates to true.

    An 'ExecTest' test consists of Python source code together with
    an (optional) Python expression.  First the Python code is
    executed.  If it throws an (uncaught) exception the test fails.
    If the optional expression is present, it is then evaluated.  If it
    evaluates to false, the test fails.  Otherwise, the test passes."""

    arguments = [
        qm.fields.TextField(
            name="source",
            title="Python Source Code",
            description="""The source code.

            This code may contain class definitions, function
            definitions, statements, and so forth.  If this code
            throws an uncaught exception, the test will fail.""",
            verbatim="true",
            multiline="true",
            default_value="pass"
            ),

        qm.fields.TextField(
            name="expression",
            title="Python Expression",
            description="""The expression to evaluate.

            If the expression evaluates to true, the test will pass,
            unless the source code above throws an uncaught exception.

            If this field is left blank, it is treated as an expression
            that is always true.""",
            verbatim="true",
            multiline="true",
            default_value="1"
            )
        ]


    def Run(self, context, result):

        # Adjust the source code.  Make sure the source ends with a
        # newline.  A user is likely to be confused by the error message
        # if it's missing.
        if not self.source:
            self.source = "\n"
        elif self.source[-1] != "\n":
            self.source += "\n" 
        global_namespace, local_namespace = make_namespaces(context)
        # Execute the source code.
        try:
            exec self.source in global_namespace, local_namespace
        except:
            # The source raised an unhandled exception, so the test
            # fails
            result.NoteException(cause="Exception executing source.")
        else:
            # The source code executed OK.  Was an additional expression
            # provided? 
            if self.expression is not None:
                # Yes; evaluate it.
                try:
                    value = eval(self.expression,
                                 global_namespace, local_namespace)
                except:
                    # Oops, an exception while evaluating the
                    # expression.  The test fails.
                    result.NoteException(cause=
                                         "Exception evaluating expression.")
                else:
                    # We evaluated the expression.  The test passes iff
                    # the expression's value is boolean true.
                    if not value:
                        result.Fail("Expression evaluates to false.",
                                    { "ExecTest.expr" : self.expression,
                                      "ExecTest.value" : repr(value) })
            else:
                # No expression provided; if we got this far, the test
                # passes. 
                pass


class BaseExceptionTest(Test):
    """Base class for tests of exceptions."""

    arguments = [
        qm.fields.TextField(
            name="source",
            title="Python Source Code",
            description="""The source code.

            This code may contain class definitions, function
            definitions, statements, and so forth.""",
            verbatim="true",
            multiline="true",
            default_value="pass"
            ),

        qm.fields.TextField(
            name="exception_argument",
            title="Exception Argument",
            description="""The expected value of the exception.

            This value is a Python expression which should evaluate
            to the same value as the exception raised.

            If this field is left blank, the value of the exception is
            ignored.""",
            default_value=""
            )
        ]


    def Run(self, context, result):

        # Adjust the exception argument.
        if string.strip(self.exception_argument) != "":
            self.exception_argument = eval(self.exception_argument, {}, {})
            self.has_exception_argument = 1
        else:
            self.has_exception_argument = 0
            
        global_namespace, local_namespace = make_namespaces(context)
        try:
            # Execute the test code.
            exec self.source in global_namespace, local_namespace
        except:
            exc_info = sys.exc_info()
            # Check the exception argument.
            self.CheckArgument(exc_info, result)
            if result.GetOutcome() != Result.PASS:
                return
            # Check that the exception itself is OK.
            self.MakeResult(exc_info, result)
        else:
            # The test code didn't raise an exception.
            result.Fail(qm.message("test did not raise"))


    def CheckArgument(self, exc_info, result):
        """Check that the exception argument matches expectations.

        'result' -- The result object for this test."""

        # Was an expected exception argument specified?
        if self.has_exception_argument:
            # Yes.  Extract the exception argument.
            argument = exc_info[1]
            if cmp(argument, self.exception_argument):
                cause = qm.message("test raised wrong argument")
                result.Fail(cause,
                            { "BaseExceptionTest.type" :
                              str(exc_info[0]),
                              "BaseExceptionTest.argument" :
                               repr(argument) })


    def MakeResult(self, exc_info, result):
        """Check the exception in 'exc_info' and construct the result.

        'result' -- The result object for this test."""

        pass



class ExceptionTest(BaseExceptionTest):
    """Check that the specified Python code raises an exception.

    An 'ExceptionTest' checks that the specified Python code raises a
    particular exception.  The test passes if the exception is an
    instance of the expected class and (optionally) if its value matches
    the expected value.  If the code fails to raise an exception, the
    test fails."""

    arguments = [
        qm.fields.TextField(
            name="exception_class",
            title="Exception Class",
            description="""The expected type of the exception.

            This value is the name of a Python class.  If the
            exception raised is not an instance of this class, the
            test fails.""",
            default_value="Exception"
            )
        ]


    def MakeResult(self, exc_info, result):
        # Make sure the exception is an object.
        if not type(exc_info[0]) in [types.ClassType, type]:
            result.Fail(qm.message("test raised non-object",
                                   exc_type=str(type(exc_info[0]))))
        # Make sure it's an instance of the right class.
        exception_class_name = exc_info[0].__name__
        if exception_class_name != self.exception_class:
            cause = qm.message("test raised wrong class",
                               class_name=exception_class_name)
            result.Fail(cause=cause)


    def CheckArgument(self, exc_info, result):
        """Check that the exception argument matches expectations.

        'result' -- The result object for this test."""

        # Was an expected argument specified?
        if self.has_exception_argument:
            # Extract the actual argument from the exception object.
            try:
                argument = exc_info[1].args
            except:
                # If the "args" were not available, then the exception
                # object does not use the documented interface given
                # for Exception.
                result.Fail("Exception object does not provide access "
                            "to arguments provided to 'raise'",
                            { "ExceptionTest.type" : str(exc_info[0]) })
                return
                
            # Now the expected argument.
            expected_argument = self.exception_argument
            # Python wraps the arguments to class exceptions in strange
            # ways, so wrap the expected argument similarly.  A 'None'
            # argument is represented by an empty tuple.
            if expected_argument is None:
                expected_argument = ()
            # Tuple arguments are unmodified.
            elif type(expected_argument) is types.TupleType:
                pass
            # A non-tuple argument is wrapped in a tuple.
            else:
                expected_argument = (expected_argument, )

            # Compare the actual argument to the expectation.
            if cmp(expected_argument, argument) != 0:
                # We got a different argument.  The test fails.
                cause = qm.message("test raised wrong argument")
                result.Fail(cause,
                            { "ExceptionTest.type" : str(exc_info[0]),
                              "ExceptionTest.argument" : repr(argument) })



class StringExceptionTest(BaseExceptionTest):
    """Check that the specified Python code raises a string exception.

    A 'StringExceptionTest' checks that the specified code throws
    an exception.  The exception must be a string and must have
    the expected value."""

    arguments = [
        qm.fields.TextField(
            name="exception_text",
            title="Exception Text",
            description="The expected exception string.",
            default_value="exception"
            )
        ]


    def MakeResult(self, exc_info, result):
        # Make sure the exception is an object.
        if not type(exc_info[0]) is types.StringType:
            result.Fail(qm.message("test raised non-string",
                                   exc_type=str(type(exc_info[0]))))
        # Make sure it's the right string.
        if exc_info[0] != self.exception_text:
            result.Fail(qm.message("test raised wrong string",
                                   text=exc_info[0]))
        


########################################################################
# functions
########################################################################

def make_namespaces(context):
    """Construct namespaces for eval/exec of Python test code.

    'context' -- The test context.

    returns -- A pair '(global_namespace, local_namespace)' of maps."""

    # The global namespace contains only the context object.
    global_namespace = {
        "context": context,
        }
    # The local namespace is empty.
    local_namespace = {
        }
    # FIXME: As of 2005-03-21, all python versions I tested with
    #        contain a bug that makes non-trivial code fail when
    #        global_namespace != local_namespace. See bug #1167300
    #
    #        Meanwhile, we use the global namespace for both, which
    #        yields the same as when calling 'exec source in globals()'

    #return global_namespace, local_namespace
    return global_namespace, global_namespace


########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/xml_result_stream.py0000664000076400007640000001330211107032221021527 0ustar  stefanstefan########################################################################
#
# File:   xml_result_stream.py
# Author: Mark Mitchell
# Date:   10/10/2001
#
# Contents:
#   XMLResultStream, XMLResultReader
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
########################################################################

import qm.xmlutil
from   qm.test.file_result_reader import FileResultReader
from   qm.test.result import Result
from   qm.test.file_result_stream import FileResultStream

########################################################################
# classes
########################################################################

class XMLResultStream(FileResultStream):
    """An 'XMLResultStream' writes out results as XML.

    An 'XMLResultStream' writes out results as XML.  This stream is
    used to write out QMTest results files.  The DTD is designed in
    such a way that if QMTest is terminated in the middle of a test
    run, the file will still be nearly valid, as long as the
    interruption did not occur in the midst of writing out an
    individual result.  The closing tag for the results file will
    be missing."""

    def __init__(self, arguments = None, **args):

        # Initialize the base class.
        super(XMLResultStream, self).__init__(arguments, **args)
        
        # Create an XML document, since the DOM API requires you
        # to have a document when you create a node.
        self.__document = qm.xmlutil.create_dom_document(
            public_id="QMTest/Result",
            document_element_tag="results")
        # Write out the prologue.
        self.file.write("\n")
        self.file.write('\n'
                        % (qm.xmlutil.make_public_id("QMTest/Result"),
                           qm.xmlutil.make_system_id("qmtest/result.dtd")))
        # Begin the list of results.
        self.file.write("\n")


    def WriteAnnotation(self, key, value):

        element = self.__document.createElement("annotation")
        element.setAttribute("key", key)
        text = self.__document.createTextNode(value)
        element.appendChild(text)
        element.writexml(self.file, addindent = " ", newl = "\n")


    def WriteResult(self, result):

        element = result.MakeDomNode(self.__document)
        element.writexml(self.file, indent = " ", addindent = " ",
                         newl = "\n")
        

    def Summarize(self):

        # Finish the list of results.
        self.file.write("\n\n")

        FileResultStream.Summarize(self)



class XMLResultReader(FileResultReader):
    """Reads in 'Result's from an XML-formatted results file.

    To write such a file, see 'XMLResultStream'."""

    def __init__(self, arguments = None, **args):

        super(XMLResultReader, self).__init__(arguments, **args)

        # Make sure that this file really is an XML result stream.
        tag = self.file.read(5)
        if tag != "" + path + " " + " ".join(arguments) + ""

        # Compute the environment.
        library_dirs = self._GetLibraryDirectories(context)
        if library_dirs:
            # Update LD_LIBRARY_PATH.  On IRIX 6, this variable
            # goes by other names, so we update them too.  It is
            # harmless to do this on other systems.
            for variable in ['LD_LIBRARY_PATH',
                             'LD_LIBRARYN32_PATH',
                             'LD_LIBRARYN64_PATH']:
                old_path = environment.get(variable)
                new_path = ':'.join(self._library_dirs)
                if old_path and new_path:
                    new_path = new_path + ':' + old_path
            environment[variable] = new_path
        else:
            # Use the default values.
            environment = None

        target = self._GetTarget(context)
        timeout = context.get("CompilerTest.execution_timeout", -1)
        status, output = target.UploadAndRun(path,
                                             arguments,
                                             environment,
                                             timeout)
        # Record the output.
        result[prefix + "output"] = result.Quote(output)
        self._CheckExecutableOutput(result, output)
        # Check the output status.
        result.CheckExitStatus(prefix, "Executable", status,
                               not self._MustExecutableExitSuccessfully())


    def _CheckOutput(self, context, result, prefix, output, diagnostics):
        """Check that the 'output' contains appropriate diagnostics.

        'context' -- The 'Context' for the test that is being
        executed.

        'result' -- The 'Result' of the test.

        'prefix' -- A string giving the prefix for any annotations to
        be added to the 'result'.

        'output' -- A string giving the output of the compiler.

        'diagnostics' -- The diagnostics that are expected for the
        compilation.

        returns -- True if there were no errors so severe as to
        prevent execution of the test."""

        # Get the compiler to use to parse the output.
        compiler = self._GetCompiler(context)
        
        # Parse the output.
        emitted_diagnostics \
            = compiler.ParseOutput(output, self._ignored_diagnostic_regexps)

        # Diagnostics that were not emitted, but should have been.
        missing_diagnostics = []
        # Diagnostics that were emitted, but should not have been.
        spurious_diagnostics = []
        # Expected diagnostics that have been matched.
        matched_diagnostics = []
        # Keep track of any errors.
        errors_occurred = 0
        
        # Loop through the emitted diagnostics, trying to match each
        # with an expected diagnostic.
        for emitted_diagnostic in emitted_diagnostics:
            # If the emitted diagnostic is an internal compiler error,
            # then the test failed.  (The compiler crashed.)
            if emitted_diagnostic.severity == 'internal_error':
                result.Fail("The compiler issued an internal error.")
                return 0
            if emitted_diagnostic.severity == "error":
                errors_occurred = 1
            # Assume that the emitted diagnostic is unexpected.
            is_expected = 0
            # Loop through the expected diagnostics, trying to find
            # one that matches the emitted diagnostic.  A single
            # emitted diagnostic might match more than one expected
            # diagnostic, so we can not break out of the loop early.
            for expected_diagnostic in diagnostics:
                if self._IsDiagnosticExpected(emitted_diagnostic,
                                              expected_diagnostic):
                    matched_diagnostics.append(expected_diagnostic)
                    is_expected = 1
            if not is_expected:
                spurious_diagnostics.append(emitted_diagnostic)
        # Any expected diagnostics for which there was no
        # corresponding emitted diagnostic are missing diagnostics.
        for expected_diagnostic in diagnostics:
            if expected_diagnostic not in matched_diagnostics:
                missing_diagnostics.append(expected_diagnostic)

        # If there were missing or spurious diagnostics, the test failed.
        if missing_diagnostics or spurious_diagnostics:
            # Compute a succint description of what went wrong.
            if missing_diagnostics and spurious_diagnostics:
                result.Fail("Missing and spurious diagnostics.")
            elif missing_diagnostics:
                result.Fail("Missing diagnostics.")
            else:
                result.Fail("Spurious diagnostics.")

            # Add annotations showing the problem.
            if spurious_diagnostics:
                self._DiagnosticsToString(result, 
                                          "spurious_diagnostics",
                                          spurious_diagnostics)
            if missing_diagnostics:
                self._DiagnosticsToString(result, 
                                          "missing_diagnostics",
                                          missing_diagnostics)

        # If errors occurred, there is no point in trying to run
        # the executable.
        return not errors_occurred


    def _CheckExecutableOutput(self, result, output):
        """Checks the output from the generated executable.

        'result' -- The 'Result' object for this test.

        'output' -- The output generated by the executable.

        If the output is unsatisfactory, 'result' is modified
        appropriately."""
        
        pass

    
    def _IsDiagnosticExpected(self, emitted, expected):
        """Returns true if 'emitted' matches 'expected'.

        'emitted' -- A 'Diagnostic emitted by the compiler.
        
        'expected' -- A 'Diagnostic' indicating an expectation about a
        diagnostic to be emitted by the compiler.

        returns -- True if the 'emitted' was expected by the
        'expected'."""

        # If the source positions do not match, there is no match.
        if expected.source_position:
            exsp = expected.source_position
            emsp = emitted.source_position

            if exsp.line and emsp.line != exsp.line:
                return 0
            if (exsp.file and (os.path.basename(emsp.file)
                               != os.path.basename(exsp.file))):
                return 0
            if exsp.column and emsp.column != exsp.column:
                return 0
        
        # If the severities do not match, there is no match.
        if (expected.severity and emitted.severity != expected.severity):
            return 0
        # If the messages do not match, there is no match.
        if expected.message and not re.search(expected.message,
                                              emitted.message):
            return 0

        # There's a match.
        return 1


    def _DiagnosticsToString(self, result, annotation, diagnostics):
        """Return a string representing the 'diagnostics'.

        'diagnostics' -- A sequence of 'Diagnostic' instances.

        returns -- A string representing the 'Diagnostic's, with one
        diagnostic message per line."""

        # Compute the string representation of each diagnostic.
        diagnostic_strings = map(str, diagnostics)
        # Insert a newline between each string.
        result[self._GetAnnotationPrefix() + annotation] \
            = result.Quote("\n".join(diagnostic_strings))
qmtest-2.4.1/qm/test/classes/ssh_host.py0000664000076400007640000001666611107032221017630 0ustar  stefanstefan########################################################################
#
# File:   ssh_host.py
# Author: Mark Mitchell
# Date:   2005-06-03
#
# Contents:
#   SSHHost, RSHHost
#
# Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
#######################################################################

from   qm.host import Host
import os
import os.path
from   qm.fields import TextField, SetField
import qm.common
import sys

########################################################################
# Classes
#######################################################################

class SSHHost(Host):
    """An 'SSHHost' is accessible via 'ssh' or a similar program."""

    # If not empty, the name of the remote host. 
    host_name = TextField()
    # The path to "ssh".
    ssh_program = TextField(
        default_value = "ssh",
        description = """The path to the remote shell program."""
        )
    # Any arguments that must be provided to "ssh". 
    ssh_args = SetField(
        TextField(description =
                  """The arguments to the remote shell program."""))
    # The path to "scp".
    scp_program = TextField(
        default_value = "scp",
        description = """The path to the remote copy program."""
        )
    # Any arguments that must be provided to "scp".
    scp_args = SetField(
        TextField(description =
                  """The arguments to the remote copy program."""))
    # The default directory on the remote system.
    default_dir = TextField(
        description = """The default directory on the remote system."""
        )

    nfs_dir = TextField(
        description = """The default directory, as seen from the local host.
    
        If not empty, 'nfs_dir' is a directory on the local machine
        that is equivalent to the default directory on the remote
        machine.  In that case, files will be copied to and from this
        directory on the local machine, rather than by using
        'scp'."""
        )

    user_name = TextField(
        description = """The user name on the remote host.

        If not empty, the user name that should be used when
        connecting to the remote host."""
        )
    
    def Run(self, path, arguments, environment = None, timeout = -1,
            relative = False):

        default_dir = self.default_dir
        if not default_dir:
            default_dir = os.curdir
        if (relative
            or (not os.path.isabs(path)
                and (path.find(os.path.sep) != -1
                     or (os.path.altsep
                         and path.find(os.path.altsep) != -1)))):
            path = os.path.join(default_dir, path)
        path, arguments = self._FormSSHCommandLine(path, arguments,
                                                   environment)
        return super(SSHHost, self).Run(path, arguments, None, timeout)


    def UploadFile(self, local_file, remote_file = None):

        if remote_file is None:
            remote_file = os.path.basename(local_file)
        if self.nfs_dir:
            remote_file = os.path.join(self.nfs_dir, remote_file)
            super(SSHHost, self).UploadFile(local_file, remote_file)
        else:    
            if self.default_dir:
                remote_file = os.path.join(self.default_dir, remote_file)
            command = self._FormSCPCommandLine(True, local_file,
                                               remote_file)
            executable = self.Executable()
            status = executable.Run(command)
            if ((sys.platform != "win32"
                 and (not os.WIFEXITED(status)
                      or os.WEXITSTATUS(status) != 0))
                or (sys.platform == "win32" and status != 0)):
                raise qm.common.QMException("could not upload file")
        

    def DownloadFile(self, remote_file, local_file = None):

        if local_file is None:
            local_file = os.path.basename(remote_file)
        if self.nfs_dir:
            remote_file = os.path.join(self.nfs_dir, remote_file)
            super(SSHHost, self).DownloadFile(remote_file, local_file)
        else:
            if self.default_dir:
                remote_file = os.path.join(self.default_dir, remote_file)
            command = self._FormSCPCommandLine(False, local_file,
                                               remote_file)
            executable = self.Executable()
            executable.Run(command)


    def DeleteFile(self, remote_file):

        if self.default_dir:
            remote_file = os.path.join(self.default_dir, remote_file)
        return self.Run("rm", [remote_file])

        
    def _FormSSHCommandLine(self, path, arguments, environment = None):
        """Form the 'ssh' command line.

        'path' -- The remote command, in the same format expected by
        'Run'. 
        
        'arguments' -- The arguments to the remote command.

        'environment' -- As for 'Run'.

        returns -- A pair '(path, arguments)' describing the command
        to run on the local machine that will execute the remote
        command."""

        command = self.ssh_args + [self.host_name]
        if self.user_name:
            command += ["-l", self.user_name]
        if environment is not None:
            command.append("env")
            for (k, v) in environment.iteritems():
                command.append("%s=%s" % (k, v))
        command.append(path)
        command += arguments

        return self.ssh_program, command


    def _FormSCPCommandLine(self, upload, local_file, remote_file):
        """Form the 'scp' command line.

        'upload' -- True iff the 'local_file' should be copied to the
        remote host.

        'local_file' -- The path to the local file.

        'remote_file' -- The path to the remote file.

        returns -- The list of arguments for a command to run on the
        local machine that will perform the file copy."""

        if self.default_dir:
            remote_file = os.path.join(self.default_dir, remote_file)
        remote_file = self.host_name + ":" + remote_file
        if self.user_name:
            remote_file = self.user_name + "@" + remote_file
        command = [self.scp_program] + self.scp_args
        if upload:
            command += [local_file, remote_file]
        else:
            command += [remote_file, local_file]

        return command    



class RSHHost(SSHHost):
    """An 'RSHHost' is an 'SSHHost' that uses 'rsh' instead of 'ssh'.

    The reason that 'RSHHost' is a separate class is that (a) that
    makes it easier for users to construct an 'SSHHost', and (b) 'rsh'
    does not return the exit code of the remote program, so 'Run'
    requires adjustment."""

    # Override the default values.
    ssh_program = TextField(
        default_value = "rsh",
        description = """The path to the remote shell program."""
        )
    scp_program = TextField(
        default_value = "rcp",
        description = """The path to the remote copy program."""
        )

    def Run(self, path, arguments, environment = None, timeout = -1):

        status, output = \
                super(RSHHost, self).Run(path, arguments,
                                         environment, timeout)
        # The exit status of 'rsh' is not the exit status of the
        # remote program.  The exit status of the remote program is
        # unavailable. 
        return (None, output)
qmtest-2.4.1/qm/test/classes/dejagnu_test.py0000664000076400007640000003753711107032221020452 0ustar  stefanstefan########################################################################
#
# File:   dejagnu_test.py
# Author: Mark Mitchell
# Date:   04/16/2003
#
# Contents:
#   DejaGNUTest
#
# Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

from   dejagnu_base import DejaGNUBase
import os
import qm
from   qm.common import QMException
from   qm.executable import RedirectedExecutable
from   qm.test.test import Test
from   qm.test.result import Result

########################################################################
# Classes
########################################################################

class DejaGNUTest(Test, DejaGNUBase):
    """A 'DejaGNUTest' emulates a DejaGNU test.

    See 'framework.exp' in the DejaGNU distribution for more
    information."""

    arguments = [
        qm.fields.AttachmentField(
            name="source_file",
            title="Source File",
            description="""The source file."""),
        ]

    PASS = "PASS"
    FAIL = "FAIL"
    KFAIL = "KFAIL"
    KPASS = "KPASS"
    XPASS = "XPASS"
    XFAIL = "XFAIL"
    WARNING = "WARNING"
    ERROR = "ERROR"
    UNTESTED = "UNTESTED"
    UNRESOLVED = "UNRESOLVED"
    UNSUPPORTED = "UNSUPPORTED"

    dejagnu_outcomes = (
        PASS, FAIL, XPASS, XFAIL, WARNING, ERROR, UNTESTED,
        UNRESOLVED, UNSUPPORTED
        )
    """The DejaGNU test outcomes."""
    
    outcome_map = {
        PASS : Result.PASS,
        FAIL : Result.FAIL,
        KFAIL : Result.FAIL,
        KPASS : Result.PASS,
        XPASS : Result.PASS,
        XFAIL : Result.FAIL,
        WARNING : Result.PASS,
        ERROR : Result.ERROR,
        UNTESTED : Result.UNTESTED,
        UNRESOLVED : Result.UNTESTED,
        UNSUPPORTED : Result.UNTESTED
        }
    """A map from DejaGNU outcomes to QMTest outcomes."""

    executable_timeout = 300
    """The number of seconds a program is permitted to run on the target."""

    RESULT_PREFIX = "DejaGNUTest.result_"
    """The prefix for DejaGNU result annotations.

    All results that would be generated by DejaGNU are inserted into
    the QMTest result as annotations beginning with this prefix.  The
    prefix is followed by an 1-indexed integer; earlier results are
    inserted with lower numbers."""

    class BuildExecutable(RedirectedExecutable):
        """A 'BuildExecutable' runs on the build machine.

        Classes derived from 'DejaGNUTest' may provide derived
        versions of this class."""

        def _StderrPipe(self):

            # Combine stdout/stderr into a single stream.
            return None


    def _GetTargetEnvironment(self, context):
        """Return additional environment variables to set on the target.

        'context' -- The 'Context' in which this test is running.
        
        returns -- A map from strings (environment variable names) to
        strings (values for those variables).  These new variables are
        added to the environment when a program executes on the
        target."""

        return {}
    

    def _RunBuildExecutable(self, context, result, file, args = [],
                            dir = None):
        """Run 'file' on the target.

        'context' -- The 'Context' in which this test is running.
        
        'result' -- The 'Result' of this test.
        
        'file' -- The path to the executable file.

        'args' -- The arguments to the 'file'.

        'dir' -- The directory in which the program should execute.

        returns -- A pair '(status, output)'.  The 'status' is the
        exit status from the command; the 'output' is the combined
        results of the standard output and standard error streams."""

        executable = self.BuildExecutable(self.executable_timeout)
        command = [file] + args
        index = self._RecordCommand(result, command)
        status = executable.Run(command, None, dir)
        output = executable.stdout
        self._RecordCommandOutput(result, index, status, output)

        return status, output

    
    def _RunTargetExecutable(self, context, result, file):
        """Run 'file' on the target.

        'context' -- The 'Context' in which this test is running.
        
        'result' -- The 'Result' of this test.
        
        'file' -- The path to the executable file.

        returns -- One of the 'dejagnu_outcomes'."""

        host = context['CompilerTable.target']
        index = self._RecordCommand(result, [file])
        environment = self._GetTargetEnvironment(context)
        status, output = host.Run(file, [], environment)
        self._RecordCommandOutput(result, index, status, output)
        # Figure out whether the execution was successful.
        if os.WIFEXITED(status) and os.WEXITSTATUS(status) == 0:
            outcome = self.PASS
        else:
            outcome = self.FAIL

        return outcome
        
        
    def _RecordDejaGNUOutcome(self, result, outcome, message,
                              expectation = None):
        """Record a DejaGNU outcome.

        'result' -- A 'Result' object.

        'outcome' -- One of the 'dejagnu_outcomes'.

        'message' -- A string, explaining the outcome.

        'expectation' -- If not 'None, the DejaGNU outcome that was
        expected."""

        # If the test was expected to fail, transform PASS or FAIL
        # into XPASS or XFAIL, respectively.
        if expectation == self.FAIL:
            if outcome == self.PASS:
                outcome = self.XPASS
            elif outcome == self.FAIL:
                outcome = self.XFAIL

        # Create an annotation corresponding to the DejaGNU outcome.
        key = "%s%d" % (self.RESULT_PREFIX, self.__next_result)
        self.__next_result += 1
        result[key] = outcome + ": " + message
        # If the test was passing until now, give it a new outcome.
        new_outcome = self.outcome_map[outcome]
        if (new_outcome
            and new_outcome != Result.PASS
            and result.GetOutcome() == Result.PASS):
            result.SetOutcome(new_outcome)
            result[Result.CAUSE] = message
        

    def _Unresolved(self, result, message):
        """Record an 'unresolved' DejaGNU outcome.

        This function is identical to 'RecordDejaGNUOutcome', except
        that the 'outcome' is always 'UNRESOLVED'."""

        self._RecordDejaGNUOutcome(result, self.UNRESOLVED, message)

        
        
    def _Error(self, message):
        """Raise an exception indicating an error in the test.

        'message' -- A description of the problem.

        This function is used when the original Tcl code in DejaGNU
        would have used the Tcl 'error' primitive.  These situations
        indicate problems with the test itself, such as incorrect
        usage of special test commands."""

        raise DejaGNUError, message

        
    def _GetSourcePath(self):
        """Return the path to the primary source file.

        returns -- A string giving the path to the primary source
        file."""

        return self.source_file.GetDataFile()


    def _GetBuild(self, context):
        """Return the GNU triplet corresponding to the build machine.
        
        'context' -- The 'Context' in which the test is running.
        
        returns -- The GNU triplet corresponding to the target
        machine, i.e,. the machine on which the compiler will run."""

        return context.get("DejaGNUTest.build") or self._GetTarget(context)

    
    def _GetTarget(self, context):
        """Return the GNU triplet corresponding to the target machine.

        'context' -- The 'Context' in which the test is running.
        
        returns -- The GNU triplet corresponding to the target
        machine, i.e,. the machine on which the programs generated by
        the compiler will run."""

        return context["DejaGNUTest.target"]
    

    def _IsNative(self, context):
        """Returns true if the build and target machines are the same.

        'context' -- The 'Context' in which this test is running.

        returns -- True if this test is runing "natively", i.e., if
        the build and target machines are the same."""

        return self._GetTarget(context) == self._GetBuild(context)
    
        
    def _SetUp(self, context):
        """Prepare to run a test.

        'context' -- The 'Context' in which this test will run.

        This method may be overridden by derived classes, but they
        must call this version."""

        super(DejaGNUTest, self)._SetUp(context)
        # The next DejaGNU result will be the first.
        self.__next_result = 1

        
    def _ParseTclWords(self, s, variables = {}):
        """Separate 's' into words, in the same way that Tcl would.

        's' -- A string.

        'variables' -- A map from variable names to values.  If Tcl
        variable substitutions are encountered in 's', the
        corresponding value from 'variables' will be used.

        returns -- A sequence of strings, each of which is a Tcl
        word.

        Command substitution is not supported and results in an
        exceptions.  Invalid inputs (like the string consisting of a
        single quote) also result in exceptions.
        
        See 'Tcl and the Tk Toolkit', by John K. Ousterhout, copyright
        1994 by Addison-Wesley Publishing Company, Inc. for details
        about the syntax of Tcl."""

        # There are no words yet.
        words = []
        # There is no current word.
        word = None
        # We are not processing a double-quoted string.
        in_double_quoted_string = 0
        # Nor are we processing a brace-quoted string.
        in_brace_quoted_string = 0
        # Iterate through all of the characters in s.
        n = 0
        while n < len(s):
            # See what the next character is.
            c = s[n]
            # A "$" indicates variable substitution.
            if c == "$" and not in_brace_quoted_string:
                k = n + 1
                if s[k] == "{":
                    # The name of the variable is enclosed in braces.
                    start = k + 1
                    finish = s.index("}", start)
                    n = finish + 1
                    var = s[start:finish]
                    v = variables[var]
                else:
                    # The following letters, numbers, and underscores make
                    # up the variable name.
                    start = k
                    while (k < len(s)
                           and (s[k].isalnum() or s[k] == "_")):
                        k += 1
                    n = k
                    finish = k
                    if start < finish:
                        var = s[start:finish]
                        v = variables[var]
                    else:
                        v = "$"
                if word is None:
                    word = v
                else:
                    word += v
                continue
            # A "[" indicates command substitution.
            elif (c == "[" and not in_brace_quoted_string
                  and n < len(s) + 1 and s[n + 1] != "]"):
                raise QMException, "Tcl command substitution is unsupported."
            # A double-quote indicates the beginning of a double-quoted
            # string.
            elif c == '"' and not in_brace_quoted_string:
                # We are now entering a new double-quoted string, or
                # leaving the old one.
                in_double_quoted_string = not in_double_quoted_string
                # Skip the quote.
                n += 1
                # The quote starts the word.
                if word is None:
                    word = ""
            # A "{" indicates the beginning of a brace-quoted string.
            elif c == '{' and not in_double_quoted_string:
                # If that's not the opening quote, add it to the
                # string.
                if in_brace_quoted_string:
                    if word is not None:
                        word = word + "{"
                    else:
                        word = "{"
                # The quote starts the word.
                if word is None:
                    word = ""
                # We are entering a brace-quoted string.
                in_brace_quoted_string += 1
                # Skip the brace.
                n += 1
            elif c == '}' and in_brace_quoted_string:
                # Leave the brace quoted string.
                in_brace_quoted_string -= 1
                # Skip the brace.
                n += 1
                # If that's not the closing quote, add it to the
                # string.
                if in_brace_quoted_string:
                    if word is not None:
                        word = word + "}"
                    else:
                        word = "}"
            # A backslash-newline is translated into a space.
            elif c == '\\' and len(s) > 1 and s[1] == '\n':
                # Skip the backslash and the newline.
                n += 2
                # Now, skip tabs and spaces.
                while n < len(s) and (s[n] == ' ' or s[n] == '\t'):
                    n += 1
                # Now prepend one space.
                n -= 1
                s[n] = " "
            # A backslash indicates backslash-substitution.
            elif c == '\\' and not in_brace_quoted_string:
                # There should be a character following the backslash.
                if len(s) == 1:
                    raise QMException, "Invalid Tcl string."
                # Skip the backslash.
                n += 1
                # See what the next character is.
                c = s[n]
                # If it's a control character, use the same character
                # in Python.
                if c in ["a", "b", "f", "n", "r", "t", "v"]:
                    c = eval('"\%s"' % c)
                    n += 1
                # "\x" indicates a hex literal.
                elif c == "x":
                    if (n < len(s)
                        and s[n + 1] in ["0", "1", "2", "3", "4", "5",
                                         "6", "7", "8", "9", "a", "b",
                                         "c", "d", "e", "f"]):
                        raise QMException, "Unsupported Tcl escape."
                    n += 1
                # "\d" where "d" is a digit indicates an octal literal.
                elif c.isdigit():
                    raise QMException, "Unsupported Tcl escape."
                # Any other character just indicates the character
                # itself.
                else:
                    n += 1
                # Add it to the current word.
                if word is not None:
                    word = word + c
                else:
                    word = c
            # A space or tab indicates a word separator.
            elif ((c == ' ' or c == '\t')
                  and not in_double_quoted_string
                  and not in_brace_quoted_string):
                # Add the current word to the list of words.
                if word is not None:
                    words.append(word)
                # Skip over the space.
                n += 1
                # Keep skipping while the leading character of s is
                # a space or tab.
                while n < len(s) and (s[n] == ' ' or s[n] == '\t'):
                    n += 1
                # Start the next word.
                word = None
            # Any other character is just added to the current word.
            else:
                if word is not None:
                    word = word + c
                else:
                    word = c
                n += 1

        # If we were working on a word when we reached the end of
        # the string, add it to the list.
        if word is not None:
            words.append(word)

        return words
qmtest-2.4.1/qm/test/classes/thread_target.py0000664000076400007640000002301311107032221020573 0ustar  stefanstefan########################################################################
#
# File:   thread_target.py
# Author: Mark Mitchell
# Date:   10/30/2001
#
# Contents:
#   QMTest ThreadTarget class.
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# imports
########################################################################

from   qm.temporary_directory import TemporaryDirectory
from   qm.test.base import *
import qm.test.cmdline
from   qm.test.command_thread import *
from   qm.test.target import *
import Queue
from   threading import *

########################################################################
# classes
########################################################################

class LocalThread(CommandThread):
    """A 'LocalThread' executes commands locally."""

    def __init__(self, target):

        CommandThread.__init__(self, target)
        self.__temporary_directory = TemporaryDirectory()
        
    
    def _RunTest(self, descriptor, context):
        """Run the test given by 'descriptor'.

        'descriptor' -- The name of the test to be run.

        'context' -- The 'Context' in which to run the test."""

        self.GetTarget()._RunTest(descriptor, context)


    def GetTemporaryDirectory(self):
        """Return the path to the temporary directory for this thread.

        returns -- The path to the temporary directory associated with
        this thread."""
        
        return self.__temporary_directory.GetPath()
        


class ThreadTarget(Target):
    """A target implementation that runs tests in local threads.

    Each thread executes one test or resource at a time."""

    arguments = [
        qm.fields.IntegerField(
            name="threads",
            title="Number of Threads",
            description="""The number of threads to devote to running tests.

            A positive integer that indicates the number of threads to
            use when running tests.  Larger numbers will allow more
            tests to be run at once.  You can experiment with this
            value to find the number that results in the fastest
            execution.""",
            default_value=1),
        ]
    
    def __init__(self, database, properties):
        """Construct a 'ThreadTarget'.

        'database' -- The 'Database' containing the tests that will be
        run.

        'properties'  -- A dictionary mapping strings (property names)
        to strings (property values)."""
        
        # Initialize the base class.
        Target.__init__(self, database, properties)

        # Create a lock to guard accesses to __ready_threads.
        self.__ready_threads_lock = Lock()
        # Create a condition variable to guard accesses to the
        # available resources table.
        self.__resources_condition = Condition()
        

    def IsIdle(self):
        """Return true if the target is idle.

        returns -- True if the target is idle.  If the target is idle,
        additional tasks may be assigned to it."""

        # Acquire the lock.  (Otherwise, a thread that terminates
        # right as we are checking for idleness may alter
        # __ready_threads.)
        self.__ready_threads_lock.acquire()
        
        # This target is idle if there are any ready threads.
        if self.__ready_threads:
            idle=1
        else:
            idle=0

        # Release the lock.
        self.__ready_threads_lock.release()

        return idle


    def Start(self, response_queue, engine=None):
        """Start the target.
        
        'response_queue' -- The 'Queue' in which the results of test
        executions are placed.

        'engine' -- The 'ExecutionEngine' that is starting the target,
        or 'None' if this target is being started without an
        'ExecutionEngine'."""

        Target.Start(self, response_queue, engine)
        
        # Build the threads.
        self.__threads = []
        for i in xrange(0, self.threads):
            # Create the new thread.
            thread = LocalThread(self)
            # Start the thread.
            thread.start()
            # Remember the thread.
            self.__threads.append(thread)

        # Initially, all threads are ready.
        self.__ready_threads = self.__threads[:]
        

    def Stop(self):
        """Stop the target.

        postconditions -- The target may no longer be used."""

        Target.Stop(self)
        
        # Send each thread a "quit" command.
        for thread in self.__threads:
            thread.Stop()
        # Now wait for each thread process to finish.
        for thread in self.__threads:
            thread.join()


    def RunTest(self, descriptor, context):
        """Run the test given by 'descriptor'.

        'descriptor' -- The 'TestDescriptor' for the test.

        'context' -- The 'Context' in which to run the test.

        Derived classes may override this method."""

        self._Trace("About to dispatch test " + descriptor.GetId())
        
        self.__ready_threads_lock.acquire()

        # The execution engine should never be trying to run a test
        # when the target is not already idle.
        assert self.__ready_threads
        # Pick an idle thread to run the test.
        thread = self.__ready_threads.pop(0)
        
        self.__ready_threads_lock.release()

        thread.RunTest(descriptor, context)
        
        self._Trace("Finished dispatching test " + descriptor.GetId())


    def _RunTest(self, descriptor, context):
        """Run the test given by 'descriptor'.

        'descriptor' -- The 'TestDescriptor' for the test.

        'context' -- The 'Context' in which to run the test.

        This method will be called from the thread that has been
        assigned the test."""

        Target.RunTest(self, descriptor, context)


    def _RecordResult(self, result):
        """Record the 'result'.

        'result' -- A 'Result' of a test or resource execution."""

        # If this is a test result, then this thread has finished all
        # of its work.
        if result.GetKind() == Result.TEST:
            self._NoteIdleThread()
        # Pass the result back to the execution engine.
        Target._RecordResult(self, result)
        
            
    def _BeginResourceSetUp(self, resource_name):
        """Begin setting up the indicated resource.

        'resource_name' -- A string naming a resource.

        returns -- If the resource has already been set up, returns a
        tuple '(outcome, map)'.  The 'outcome' indicates the outcome
        that resulted when the resource was set up; the 'map' is a map
        from strings to strings indicating properties added by this
        resource.  Otherwise, returns 'None', but marks the resource
        as in the process of being set up; it is the caller's
        responsibility to finish setting it up by calling
        '_FinishResourceSetUp'."""

        # Acquire the lock.
        self.__resources_condition.acquire()
        try:
            # Loop until either we are assigned to set up the resource
            # or until some other thread has finished setting it up.
            while 1:
                rop = Target._BeginResourceSetUp(self, resource_name)
                # If this is the first thread to call _BeginResourceSetUp
                # for this thread will set up the resource.
                if not rop:
                    return rop
                # If this resource has already been set up, we do not
                # need to do anything more.
                if rop[1]:
                    return rop
                # Otherwise, some other thread is in the process of
                # setting up this resource so we just wait for it to
                # finish its job.
                self.__resources_condition.wait()
        finally:
            # Release the lock.
            self.__resources_condition.release()
                

    def _FinishResourceSetUp(self, resource, result, properties):

        # Acquire the lock.
        self.__resources_condition.acquire()
        # Record the fact that the resource is set up.
        rop = Target._FinishResourceSetUp(self, resource, result, properties)
        # Tell all the other threads that the resource has been set
        # up.
        self.__resources_condition.notifyAll()
        # Release the lock.
        self.__resources_condition.release()

        return rop

        
    def _NoteIdleThread(self):
        """Note that the current thread.

        This method is called by the thread when it has completed a
        task."""

        # Acquire the lock.  (Otherwise, IsIdle might be called right
        # as we are accessing __ready_threads.)
        self.__ready_threads_lock.acquire()

        # Now that we have acquired the lock make sure that we release
        # it, even if an exception occurs.
        try:
            thread = currentThread()
            assert thread not in self.__ready_threads
            self.__ready_threads.append(thread)
        finally:
            # Release the lock.
            self.__ready_threads_lock.release()


    def _Trace(self, message):
        """Write a trace 'message'.

        'message' -- A string to be output as a trace message."""

        if __debug__:
            tracer = qm.test.cmdline.get_qmtest().GetTracer()
            tracer.Write(message, "thread_target")


    def _GetTemporaryDirectory(self):

        return currentThread().GetTemporaryDirectory()
qmtest-2.4.1/qm/test/classes/pickle_result_stream.py0000664000076400007640000002406611107032221022207 0ustar  stefanstefan########################################################################
#
# File:   pickle_result_stream.py
# Author: Mark Mitchell
# Date:   11/25/2002
#
# Contents:
#   PickleResultStream, PickleResultReader
#
# Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
########################################################################

import types
import cPickle
import struct
import qm.fields
from   qm.test.file_result_stream import FileResultStream
from   qm.test.file_result_reader import FileResultReader

########################################################################
# Constants
########################################################################

# A subtlety is that because of how extension classes are loaded, we
# can't use the standard trick of using a nonce class for our sentinel,
# because the unpickler won't be able to find the class definition.  But
# 'None' has no other meaning in our format, so works fine.
_annotation_sentinel = None
"""The sentinel value that marks the beginning of an annotation."""

# Network byte order, 4 byte unsigned int
_int_format = "!I"
_int_size = struct.calcsize(_int_format)

########################################################################
# Classes
########################################################################

class PickleResultStream(FileResultStream):
    """A 'PickleResultStream' writes out results as Python pickles.

    See also 'PickleResultReader', which does the reverse."""

    _max_pinned_results = 1000
    """A limit on how many `Result's to pin in memory at once.

    Pickling an object normally pins it in memory; this is necessary
    to ensure correct behaviour when pickling multiple references to
    the same object.  We know that `Result's can't refer to each
    other, so this pinning is useless overhead; however, clearing the
    cache at every call to `WriteResult' slows down both pickling and
    unpickling by about a factor of two.  As a solution, any given
    `PickleResultStream', will clear its cache after
    `_max_pinned_results' calls to WriteResult.  This cache-clearing
    technique causes a very minor slowdown on small result streams,
    and a substantial speedup on large result streams."""

    _format_version = 1
    """The version number of the format we write.

    This is bumped every time the format is changed, to make sure that
    we can retain backwards compatibility.

    "Version 0" contains no version number, and is simply a bunch
    of 'Result's pickled one after another.

    "Version 1", and all later versions, contain a pickled version
    number as the first thing in the file.  In version 1, this is
    followed by a 4-byte unsigned integer in network byte order giving
    the address of the first annotation, followed by the file proper.
    The file proper is composed of a bunch of pickled 'Result's,
    followed by a pickled sentinel value (None), followed by a 4-byte
    unsigned integer in network-byte order, followed by the beginning of
    a new pickle whose first item is a annotation tuple, and following
    items are more 'Result's, and then another sentinel value, and so
    on.  An annotation tuple is a tuple of n items, the first of which
    is a string tagging the type of annotation, and the rest of which
    have an interpretation that depends on the tag found.  The only tag
    currently defined is "annotation", which is followed by two string
    elements giving respectively the key and the value.  The 4-byte
    integers always point to the file address of the next such integer,
    except for the last, which has a value of 0; they are used to
    quickly find all annotations."""

    arguments = [
        qm.fields.IntegerField(
            name = "protocol_version",
            description = """The pickle protocol version to use.

            There are multiple versions of the pickle protocol; in
            general, higher numbers correspond to faster operation and
            more compact files, but may produce files that cannot be
            understood by older versions of Python.

            As of 2003-06-20, the defined protocol versions are:
               0: Traditional ASCII-only format.
               1: Traditional binary format.
               2: New binary format.
              -1: Equivalent to the highest version supported by your
                  Python release.
            Pickle versions 0 and 1 can be understood by any version
            of Python; version 2 pickles can only be created or
            understood by Python 2.3 and newer.  (See PEP 307 for
            details.)

            Currently the default version is 1.

            """,
            default_value = 1,
        ),
    ]

    _is_binary_file = 1

    def __init__(self, arguments = None, **args):

        # Initialize the base class.
        super(PickleResultStream, self).__init__(arguments, **args)
        # Create initial pickler.
        self._ResetPickler()
        # We haven't processed any `Result's yet.
        self.__processed = 0

        # Write out version number.
        self.__pickler.dump(self._format_version)
        # We have no previous annotations.
        self.__last_annotation = None
        # Write out annotation header.
        self._WriteAnnotationPtr()


    def _ResetPickler(self):

        self.__pickler = cPickle.Pickler(self.file, self.protocol_version)


    def _WriteAnnotationPtr(self):

        new_annotation = self.file.tell()
        if self.__last_annotation is not None:
            self.file.seek(self.__last_annotation)
            self.file.write(struct.pack(_int_format, new_annotation))
            self.file.seek(new_annotation)
        self.file.write(struct.pack(_int_format, 0))
        self.__last_annotation = new_annotation
        self._ResetPickler()


    def WriteAnnotation(self, key, value):

        assert isinstance(key, types.StringTypes)
        assert isinstance(value, types.StringTypes)
        self.__pickler.dump(_annotation_sentinel)
        self._WriteAnnotationPtr()
        self.__pickler.dump(("annotation", key, value))


    def WriteResult(self, result):

        self.__pickler.dump(result)
        self.__processed += 1
        # If enough results have been pickeled, clear the pickling
        # cache.
        if not self.__processed % self._max_pinned_results:
            self.__pickler.clear_memo()


            
class PickleResultReader(FileResultReader):
    """A 'PickleResultReader' reads in results from pickle files.

    See also 'PickleResultStream', which does the reverse."""

    def __init__(self, arguments = None, **args):

        super(PickleResultReader, self).__init__(arguments, **args)
        self._ResetUnpickler()

        self._annotations = {}

        # Check for a version number
        try:
            version = self.__unpickler.load()
        except (EOFError, cPickle.UnpicklingError):
            raise FileResultReader.InvalidFile, \
                  "file is not a pickled result stream"
        
        if not isinstance(version, int):
            # Version 0 file, no version number; in fact, we're
            # holding a 'Result'.  So we have no metadata to load and
            # should just rewind.
            self.file.seek(0)
            self._ResetUnpickler()
        elif version == 1:
            self._ReadMetadata()
        else:
            raise QMException, "Unknown format version %i" % (version,)


    def _ResetUnpickler(self):

        self.__unpickler = cPickle.Unpickler(self.file)


    def _ReadAddress(self):

        raw = self.file.read(_int_size)
        return struct.unpack(_int_format, raw)[0]
        

    def _ReadMetadata(self):

        # We've read in the version number; next few bytes are the
        # address of the first annotation.
        addr = self._ReadAddress()
        # That advanced the read head to the first 'Result'; save this
        # spot to return to later.
        first_result_addr = self.file.tell()
        while addr:
            # Go the the address.
            self.file.seek(addr)
            # First four bytes are the next address.
            addr = self._ReadAddress()
            # Then we restart the pickle stream...
            self._ResetUnpickler()
            # ...and read in the annotation here.
            annotation_tuple = self.__unpickler.load()
            kind = annotation_tuple[0]
            if kind == "annotation":
                (key, value) = annotation_tuple[1:]
                self._annotations[key] = value
            else:
                print "Unknown annotation type '%s'; ignoring" % (kind,)
            # Now loop back and jump to the next address.

        # Finally, rewind back to the beginning for the reading of
        # 'Result's.
        self.file.seek(first_result_addr)
        self._ResetUnpickler()


    def GetAnnotations(self):

        return self._annotations


    def GetResult(self):

        while 1:
            try:
                thing = self.__unpickler.load()
            except (EOFError, cPickle.UnpicklingError):
                # When reading from a StringIO, no EOFError will be
                # raised when the unpickler tries to read from the file.
                # Instead, the unpickler raises UnpicklingError when it
                # tries to unpickle the empty string.
                return None
            else:
                if thing is _annotation_sentinel:
                    # We're looking for results, but this is an annotation,
                    # so skip over it.
                    # By skipping past the address...
                    self.file.seek(_int_size, 1)
                    self._ResetUnpickler()
                    # ...and the annotation itself.
                    self.__unpickler.noload()
                    # Now loop.
                else:
                    # We actually got a 'Result'.
                    return thing

########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/dg_test.py0000664000076400007640000004223311107032221017414 0ustar  stefanstefan########################################################################
#
# File:   dg_test.py
# Author: Mark Mitchell
# Date:   04/17/2003
#
# Contents:
#   DGTest
#
# Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

from   dejagnu_test import DejaGNUTest
import fnmatch
import os
from   qm.test.result import Result
from   qm.fields import BooleanField
import re

########################################################################
# Classes
########################################################################

class DGTest(DejaGNUTest):
    """A 'DGTest' is a test using the DejaGNU 'dg' driver.

    This test class emulates the 'dg.exp' source file in the DejaGNU
    distribution."""

    class DGException(Exception):
        """The exception class raised by 'DGTest'.

        When a 'DGTest' method detects an error situation, it raises
        an exception of this type."""

        pass



    __dg_command_regexp \
         = re.compile(r"{[ \t]+dg-([-a-z]+)[ \t]+(.*)[ \t]+}[^}]*$")
    """A regular expression matching commands embedded in the source file."""

    # The values of these constants have been chosen so that they
    # match the valid values for the 'dg-do' command.
    KIND_PREPROCESS = "preprocess"
    KIND_COMPILE = "compile"
    KIND_ASSEMBLE = "assemble"
    KIND_LINK = "link"
    KIND_RUN = "run"

    keep_output = BooleanField(default_value=False,
        description="""True if the output file should be retained
        after the test is complete.  Otherwise, it is removed.""")

    _default_kind = KIND_COMPILE
    """The default test kind.

    This value can be overridden by a 'dg-do' command in the test file."""
    
    __test_kinds = (
        KIND_PREPROCESS,
        KIND_COMPILE,
        KIND_ASSEMBLE,
        KIND_LINK,
        KIND_RUN
        )
    """The kinds of tests supported by 'dg.exp'."""

    __DIAG_BOGUS = "bogus"
    __DIAG_ERROR = "error"
    __DIAG_WARNING = "warning"
    
    __diagnostic_descriptions = {
        __DIAG_ERROR : "errors",
        __DIAG_WARNING : "warnings",
        __DIAG_BOGUS : "bogus messages",
        "build" : "build failure",
        }
    """A map from dg diagnostic kinds to descriptive strings."""
    
    def _RunDGTest(self, tool_flags, default_options, context, result,
                   path = None,
                   default_kind = None,
                   keep_output = None):
        """Run a 'dg' test.

        'tool_flags' -- A list of strings giving a set of options to be
        provided to the tool being tested.
        
        'default_options' -- A list of strings giving a default set of
        options to be provided to the tool being tested.  These options
        can be overridden by an embedded 'dg-options' command in the
        test itself.
        
        'context' -- The 'Context' in which this test is running.

        'result' -- The 'Result' of the test execution.

        'path' -- The path to the test file.  If 'None', the main test
        file path is used.
        
        'default_kind' -- The kind of test to perform.  If this value
        is 'None', then 'self._default_kind' is used.

        'keep_output' -- True if the output file should be retained
        after the test is complete.  Otherwise, it is removed.

        This function emulates 'dg-test'."""
        
        # Intialize.
        if default_kind is None:
            default_kind = self._default_kind
        self._kind = default_kind
        self._selected = None
        self._expectation = None
        self._options = list(default_options)
        self._diagnostics = []
        self._excess_errors_expected = False
        self._final_commands = []
        # Iterate through the test looking for embedded commands.
        line_num = 0
        if not path:
            path = self._GetSourcePath()
        root = self.GetDatabase().GetRoot()
        if path.startswith(root):
            self._name = path[len(root) + 1:]
        else:
            # We prepend "./" for output compatibility with DejaGNU.
            self._name = os.path.join(".", os.path.basename(path))
        for l in open(path).xreadlines():
            line_num += 1
            m = self.__dg_command_regexp.search(l)
            if m:
                f = getattr(self, "_DG" + m.group(1).replace("-", "_"))
                args = self._ParseTclWords(m.group(2),
                                           { "srcdir" : root })
                f(line_num, args, context)

        # If this test does not need to be run on this target, stop.
        if self._selected == 0:
            self._RecordDejaGNUOutcome(result,
                                       self.UNSUPPORTED,
                                       self._name)
            return

        # Run the tool being tested and process its output.
        file = self._RunDGToolPortion(path, tool_flags, context, result)

        # Run the executable generated (if applicable).
        self._RunDGExecutePortion(file, context, result)

        # Run dg-final tests.
        for c, a in self._final_commands:
            self._ExecuteFinalCommand(c, a, context, result)

        # For backward compatibility the function parameter overrides
        # the extension argument, if defined.
        do_keep_output = keep_output is None and self.keep_output or keep_output
        # Remove the output file.
        if not do_keep_output:
            try:
                os.remove(file)
            except:
                pass

    def _RunDGToolPortion(self, path, tool_flags, context, result):
        """Perform the tool-running portions of a DG test.

        Calls '_RunTool' and processes its output.

        returns -- The filename of the generated file."""

        # Run the tool being tested.
        output, file = self._RunTool(path, self._kind,
                                     tool_flags + self._options,
                                     context,
                                     result)

        # Check to see if the right diagnostic messages appeared.
        # This algorithm takes time proportional to the number of
        # lines in the output times the number of expected
        # diagnostics.  One could do much better, but DejaGNU does
        # not.
        for l, k, x, p, c in self._diagnostics:
            # Remove all occurrences of this diagnostic from the
            # output.
            if l is not None:
                ldesc = "%d" % l
                l = ":%s:" % ldesc
            else:
                ldesc = ""
                l = ldesc
            output, matched = re.subn(r"(?m)^.+" + l + r".*(" + p + r").*$",
                                      "", output)
            # Record an appropriate test outcome.
            message = ("%s %s (test for %s, line %s)"
                       % (self._name, c,
                          self.__diagnostic_descriptions[k], ldesc))
            if matched:
                if k == self.__DIAG_BOGUS:
                    outcome = self.FAIL
                else:
                    outcome = self.PASS
            else:
                if k == self.__DIAG_BOGUS:
                    outcome = self.PASS
                else:
                    outcome = self.FAIL
                    
            self._RecordDejaGNUOutcome(result, outcome, message, x)

        # Remove tool-specific messages that can be safely ignored.
        output = self._PruneOutput(output)
            
        # Remove leading blank lines.
        output = re.sub(r"^\n+", "", output)
        # If there's any output left, the test fails.
        message = self._name + " (test for excess errors)"
        if self._excess_errors_expected:
            expected = self.FAIL
        else:
            expected = self.PASS
        if output != "":
            self._RecordDejaGNUOutcome(result, self.FAIL,
                                       message, expected)
            result["DGTest.excess_errors"] = result.Quote(output)
        else:
            self._RecordDejaGNUOutcome(result, self.PASS,
                                       message, expected)

        return file


    def _RunDGExecutePortion(self, file, context, result):
        """Perform the executable-running portions of a DG test.

        If this is a "run" test, runs the executable generated by the
        tool and checks its output."""

        # Run the generated program.
        if self._kind == "run":
            if not os.path.exists(file):
                message = (self._name
                           + " compilation failed to produce executable")
                self._RecordDejaGNUOutcome(result, self.WARNING, message)
            else:
                outcome = self._RunTargetExecutable(context, result, file)
                # Add an annotation indicating what happened.
                message = self._name + " execution test"
                self._RecordDejaGNUOutcome(result, outcome, message,
                                           self._expectation)


    def _ExecuteFinalCommand(self, command, args, context, result):
        """Run a command specified with 'dg-final'.

        'command' -- A string giving the name of the command.
        
        'args' -- A list of strings giving the arguments (if any) to
        that command.

        'context' -- The 'Context' in which this test is running.

        'result' -- The 'Result' of this test."""

        raise self.DGException, \
              'dg-final command \"%s\" is not implemented' % command
        
        
    def _PruneOutput(self, output):
        """Remove unintersting messages from 'output'.

        'output' -- A string giving the output from the tool being
        tested.

        returns -- A modified version of 'output'.  This modified
        version does not contain tool output messages that are
        irrelevant for testing purposes."""

        raise NotImplementedError
    
        
    def _RunTool(self, path, kind, options, context, result):
        """Run the tool being tested.

        'path' -- The path to the test file.
        
        'kind' -- The kind of test to perform.

        'options' -- A list of strings giving command-line options to
        provide to the tool.

        'context' -- The 'Context' for the test execution.

        'result' -- The QMTest 'Result' for the test.

        returns -- A pair '(output, file)' where 'output' consists of
        any messages produced by the compiler, and 'file' is the name
        of the file produced by the compilation, if any."""

        raise NotImplementedError
        
        
    def _DGdo(self, line_num, args, context):
        """Emulate the 'dg-do' command.

        'line_num' -- The line number at which the command was found.

        'args' -- The arguments to the command, as a list of
        strings.

        'context' -- The 'Context' in which the test is running."""

        if len(args) > 2:
            self._Error("dg-do: too many arguments")

        if len(args) >= 2:
            code = self._ParseTargetSelector(args[1], context)
            if code == "S":
                self._selected = 1
            elif code == "N":
                if self._selected != 1:
                    self._selected = 0
            elif code == "F":
                self._expectation = Result.FAIL
        else:
            self._selected = 1
            self._expectation = Result.PASS

        kind = args[0]
        if kind not in self.__test_kinds:
            self._Error("dg-do: syntax error")
            
        self._kind = kind


    def _DGfinal(self, line_num, args, context):
        """Emulate the 'dg-final' command.

        'line_num' -- The line number at which the command was found.

        'args' -- The arguments to the command, as a list of
        strings.

        'context' -- The 'Context' in which the test is running."""

        if len(args) > 1:
            self._Error("dg-final: too many arguments")

        words = self._ParseTclWords(args[0])
        self._final_commands.append((words[0], words[1:]))
            
        
    def _DGoptions(self, line_num, args, context):
        """Emulate the 'dg-options' command.

        'line_num' -- The line number at which the command was found.

        'args' -- The arguments to the command, as a list of
        strings.

        'context' -- The 'Context' in which the test is running."""

        if len(args) > 2:
            self._Error("'dg-options': too many arguments")

        if len(args) >= 2:
            code = self._ParseTargetSelector(args[1], context)
            if code == "S":
                self._options = self._ParseTclWords(args[0])
            elif code != "N":
                self._Error("'dg-options': 'xfail' not allowed here")
        else:
            self._options = self._ParseTclWords(args[0])


    def _DGbogus(self, line_num, args, context):
        """Emulate the 'dg-bogus' command.

        'line_num' -- The number at which the command was found.

        'args' -- The arguments to the command, as a list of
        strings.

        'context' -- The 'Context' in which the test is running."""
        
        self.__ExpectDiagnostic(self.__DIAG_BOGUS, line_num, args, context)


    def _DGwarning(self, line_num, args, context):
        """Emulate the 'dg-warning' command.

        'line_num' -- The number at which the command was found.

        'args' -- The arguments to the command, as a list of
        strings.

        'context' -- The 'Context' in which the test is running."""

        self.__ExpectDiagnostic(self.__DIAG_WARNING, line_num, args, context)

        
    def _DGerror(self, line_num, args, context):
        """Emulate the 'dg-error' command.

        'line_num' -- The number at which the command was found.

        'args' -- The arguments to the command, as a list of
        strings.

        'context' -- The 'Context' in which the test is running."""

        self.__ExpectDiagnostic(self.__DIAG_ERROR, line_num, args, context)


    def _DGexcess_errors(self, line_num, args, context):
        """Emulate the 'dg-excess-errors' command.

        'line_num' -- The line number at which the command was found.

        'args' -- The arguments to the command, as a list of
        strings.

        'context' -- The 'Context' in which the test is running."""

        if len(args) > 2:
            self._Error("'dg-excess-errors': too many arguments")

        if len(args) >= 2:
            code = self._ParseTargetSelector(args[1], context)
            if code in ("F", "S"):
                self._excess_errors_expected = True
        else:
            self._excess_errors_expected = True


    def __ExpectDiagnostic(self, kind, line_num, args, context):
        """Register an expected diagnostic.

        'kind' -- The kind of diagnostic expected.

        'line_num' -- The number at which the command was found.

        'args' -- The arguments to the command, as a list of
        strings.

        'context' -- The 'Context' in which the test is running."""

        if len(args) > 4:
            self._Error("'dg-" + kind + "': too many arguments")

        if len(args) >= 4:
            l = args[3]
            if l == "0":
                line_num = None
            elif l != ".":
                line_num = int(args[3])

        # Parse the target selector, if any.
        expectation = self.PASS
        if len(args) >= 3:
            code = self._ParseTargetSelector(args[2], context)
            if code == "N":
                return
            if code == "F":
                expectation = self.FAIL

        if len(args) >= 2:
            comment = args[1]
        else:
            comment = ""
            
        self._diagnostics.append((line_num, kind, expectation,
                                  args[0], comment))
        
        
    def _ParseTargetSelector(self, selector, context):
        """Parse the target 'selector'.

        'selector' -- A target selector.

        'context' -- The 'Context' in which the test is running.

        returns -- For a 'target' selector, 'S' if this test should be
        run, or 'N' if it should not.  For an 'xfail' selector, 'F' if
        the test is expected to fail; 'P' if if not.

        This function emulates dg-process-target."""

        # Split the selector into words.  In the DejaGNU code, this
        # operation is accomplished by treating the string as Tcl
        # list.
        words = selector.split()
        # Check the first word.
        if words[0] != "target" and words[0] != "xfail":
            raise QMException, "Invalid selector."
        # The rest of the selector is a space-separate list of
        # patterns.  See if any of them are matched by the current
        # target platform.
        target = self._GetTarget(context)
        match = 0
        for p in words[1:]:
            if (p == "native" and self._IsNative(context)
                or fnmatch.fnmatch(target, p)):
                match = 1
                break

        if words[0] == "target":
            if match:
                return "S"
            else:
                return "N"
        else:
            if match:
                return "F"
            else:
                return "P"
        
qmtest-2.4.1/qm/test/classes/xml_expectation_database.py0000664000076400007640000000507511107032221023015 0ustar  stefanstefan########################################################################
#
# File:   xml_expectation_database.py
# Author: Stefan Seefeld
# Date:   2007-09-18
#
# Contents:
#   QMTest XMLExpectationDatabase extension class.
#
# Copyright (c) 2007 by CodeSourcery, Inc.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

from qm.fields import TextField
from qm.test.expectation_database import ExpectationDatabase
from qm.test.result import Result
from qm.test.base import load_results
from qm.xmlutil import *
import re

########################################################################
# Classes
########################################################################

class XMLExpectationDatabase(ExpectationDatabase):
    """An 'XMLExpectationDatabase' reads expectations from
    an XML file."""

    file_name = TextField()


    def __init__(self, **args):

        super(XMLExpectationDatabase, self).__init__(**args)
        self._expectations = []
        document = load_xml(open(self.file_name))
        root = document.documentElement
        for e in root.getElementsByTagName('expectation'):
            test_id = e.getAttribute('test_id')
            outcome = {'pass':Result.PASS,
                       'fail':Result.FAIL,}[e.getAttribute('outcome')]
            filters = {}
            for a in e.getElementsByTagName('annotation'):
                filters[a.getAttribute('name')] = a.getAttribute('value')
            description = e.getElementsByTagName('description')
            if description: description = get_dom_text(description[0])
            self._expectations.append((test_id, outcome, filters, description))


    def Lookup(self, test_id):

        
        outcome, description = Result.PASS, ''
        for rule_id, rule_outcome, rule_annotations, rule_description in self._expectations:
            if re.match(rule_id, test_id):
                match = True
                for a in rule_annotations.iteritems():
                    if (a[0] not in self.testrun_parameters or
                        not re.match(a[1], self.testrun_parameters[a[0]])):
                        match = False
                if match:
                    outcome = rule_outcome
                    description = rule_description
        return Result(Result.TEST, test_id, outcome,
                      annotations={'description':description})
qmtest-2.4.1/qm/test/classes/classes.qmc0000664000076400007640000000473411107032221017554 0ustar  stefanstefan

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

qmtest-2.4.1/qm/test/classes/__init__.py0000664000076400007640000000101711107032221017515 0ustar  stefanstefan########################################################################
#
# File:   __init__.py
# Author: Mark Mitchell
# Date:   2003-11-23
#
# Contents:
#   Module initialization.
#
# Copyright (c) 2001 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/command_host.py0000664000076400007640000000340611107032221020435 0ustar  stefanstefan########################################################################
#
# File:   command_host.py
# Author: Stefan Seefeld
# Date:   2006-10-24
#
# Contents:
#   CommandHost
#
# Copyright (c) 2006 by CodeSourcery, Inc.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
#######################################################################

from qm.fields import TextField, SetField
from qm.test.classes import local_host
import sys, os, os.path

########################################################################
# Classes
#######################################################################

class CommandHost(local_host.LocalHost):
    """A CommandHost runs an executable through a command.

    The 'command' parameter specifies the command to use, while
    'command_args' contains a set of arguments to be passed to the
    command."""


    command = TextField(description="Name of the command"
                        " used to run the executable.")
    command_args = SetField(TextField(description="Set of arguments"
                                      " passed to the command."))

    def Run(self, path, arguments, environment = None, timeout = -1,
            relative = False):

        if (relative
            or (not os.path.isabs(path)
                and (path.find(os.path.sep) != -1
                     or (os.path.altsep
                         and path.find(os.path.altsep) != -1)))):
            path = os.path.join(os.curdir, path)
        arguments = self.command_args + [path] + arguments
        return local_host.LocalHost.Run(self, self.command,
                                        arguments, environment, timeout)
qmtest-2.4.1/qm/test/classes/process_target.py0000664000076400007640000002022711107032221021006 0ustar  stefanstefan########################################################################
#
# File:   process_target.py
# Author: Mark Mitchell
# Date:   07/24/2002
#
# Contents:
#   ProcessTarget
#
# Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
########################################################################

import cPickle
import os
import qm.executable
import qm.test.cmdline
from   qm.test.target import *

########################################################################
# Classes
########################################################################

class ProcessTarget(Target):
    """A 'ProcessTarget' runs tests in child processes."""

    arguments = [
        qm.fields.IntegerField(
            name="processes",
            title="Number of Processes",
            description="""The number of processes to devote to running tests.

            A positive integer that indicates the number of processes to
            use when running tests.  Larger numbers will allow more
            tests to be run at once.  You can experiment with this
            value to find the number that results in the fastest
            execution.""",
            default_value=1),
        qm.fields.TextField(
            name="database_path",
            title="Database Path",
            description="""The path to the test database.

            A string giving the directory containing the test
            database.  If this value is the empty string, QMTest uses
            the path provided on the command line.""",
            default_value=""),
        qm.fields.TextField(
            name="qmtest",
            title="QMTest Path",
            description="""The path to the QMTest executable.

            A string giving the file name of the 'qmtest' executable
            program.  This path is used to invoke QMTest.""",
            default_value=""),
        ]

    class QMTestExecutable(qm.executable.Executable):
        """A 'QMTestExecutable' redirects commands to a child process."""

        def _InitializeParent(self):

            self.command_pipe = os.pipe()
            self.response_pipe = os.pipe()


        def _InitializeChild(self):

            # Close the write end of the command pipe.
            os.close(self.command_pipe[1])
            # And the read end of the response pipe.
            os.close(self.response_pipe[0])
            # Connect the pipes to the standard input and standard
            # output for the child.
            os.dup2(self.command_pipe[0], sys.stdin.fileno())
            os.dup2(self.response_pipe[1], sys.stdout.fileno())

            
        
    def __init__(self, database, properties):
        """Construct a new 'ProcessTarget'.

        'database' -- The 'Database' containing the tests that will be
        run.
    
        'properties'  -- A dictionary mapping strings (property names)
        to strings (property values)."""
        
        # Initialize the base class.
        Target.__init__(self, database, properties)


    def IsIdle(self):
        """Return true if the target is idle.

        returns -- True if the target is idle.  If the target is idle,
        additional tasks may be assigned to it."""

        return self.__idle_children


    def Start(self, response_queue, engine=None):
        """Start the target.
        
        'response_queue' -- The 'Queue' in which the results of test
        executions are placed.

        'engine' -- The 'ExecutionEngine' that is starting the target,
        or 'None' if this target is being started without an
        'ExecutionEngine'."""

        Target.Start(self, response_queue, engine)

        # There are no children yet.
        self.__children = []
        self.__idle_children = []
        self.__busy_children = []
        self.__children_by_fd = {}
        
        # Determine the test database path to use.
        database_path = self.database_path
        if not database_path:
            database_path = self.GetDatabase().GetPath()
        # See if the path to the QMTest binary was set in the
        # target configuration.
        qmtest_path = self.qmtest
        if not qmtest_path:
            # If not, fall back to the value determined when
            # QMTest was invoked.
            qmtest_path \
                = qm.test.cmdline.get_qmtest().GetExecutablePath()
            # If there is no such value, use a default value.
            if not qmtest_path:
                qmtest_path = "/usr/local/bin/qmtest"
        # Construct the command we want to invoke.
        arg_list = (self._GetInterpreter() +
                    [ qmtest_path, '-D', database_path, "remote" ])

        # Create the subprocesses.
        for x in xrange(self.processes):
            # Create two pipes: one to write commands to the remote
            # QMTest, and one to read responses.
            e = ProcessTarget.QMTestExecutable()
            child_pid = e.Spawn(arg_list)
            
            # Close the read end of the command pipe.
            os.close(e.command_pipe[0])
            # And the write end of the response pipe.
            os.close(e.response_pipe[1])

            # Remember the child.
            child = (child_pid,
                     os.fdopen(e.response_pipe[0], "r"),
                     os.fdopen(e.command_pipe[1], "w", 0))
            self.__children.append(child)
            self.__idle_children.append(child)
            self.__children_by_fd[e.response_pipe[0]] = child
            engine.AddInputHandler(e.response_pipe[0], self.__ReadResults)


    def Stop(self):
        """Stop the target.

        postconditions -- The target may no longer be used."""

        # Stop the children.
        for child in self.__children:
            try:
                cPickle.dump("Stop", child[2])
                child[2].close()
            except:
                pass
        # Read any remaining results.
        while self.__busy_children:
            self.__ReadResults(self.__busy_children[0][1].fileno())
        # Wait for the children to terminate.
        while self.__children:
            child = self.__children.pop()
            os.waitpid(child[0], 0)
            
        Target.Stop(self)


    def RunTest(self, descriptor, context):
        """Run the test given by 'test_id'.

        'descriptor' -- The 'TestDescriptor' for the test.

        'context' -- The 'Context' in which to run the test."""

        # Use the child process at the head of the list.
        child = self.__idle_children.pop(0)
        self.__busy_children.append(child)
        # Write the test to the file.
        try:
            cPickle.dump(("RunTest", descriptor.GetId(), context),
                         child[2])
        except:
            # We could not write to the child.  (One situation in
            # which this happens is that the child process has been
            # killed.)
            result = Result(Result.TEST, descriptor.GetId())
            result.NoteException()
            self._RecordResult(result)
            self.__idle_children.append(child)
            

    def _GetInterpreter(self):
        """Return the interpreter to use.

        returns -- A list giving the path to an interpreter, and
        arguments to provide the interpreter.  This interpreter is
        used to run QMTest.  If '[]' is returned, then no intepreter
        is used."""

        return []
        

    def __ReadResults(self, fd):
        """Read results from one of the children.

        'fd' -- The descriptor from which the results should be read."""
        
        child = self.__children_by_fd[fd]
        try:
            results = cPickle.load(child[1])
            idle = None
            for result in results:
                self._RecordResult(result)
                if not idle and result.GetKind() == Result.TEST:
                    self.__idle_children.append(child)
                    self.__busy_children.remove(child)
                    idle = 1
        except EOFError:
            self.__idle_children.append(child)
            if child in self.__busy_children:
                self.__busy_children.remove(child)
qmtest-2.4.1/qm/test/classes/compilation_test_database.py0000664000076400007640000001557411107032221023174 0ustar  stefanstefan########################################################################
#
# File:   compilation_test_database.py
# Author: Stefan Seefeld
# Date:   2006-07-28
#
# Contents:
#   CompilationTestDatabase.
#
# Copyright (c) 2006 by CodeSourcery, Inc.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# imports
########################################################################

import os, dircache
from   qm.common import parse_string_list
from   qm.extension import get_class_arguments
from   qm.fields import *
import qm.label
import qm.structured_text
import qm.test.base
from   qm.test.database import *
from   qm.test.suite import *
from   qm.test import context
from   qm.test.classes.explicit_suite import ExplicitSuite
from   qm.test.classes import compilation_test
from   qm.test.classes.compiler import Compiler
from   qm.test.classes.compiler_test import CompilationStep
from   qm.test.classes.compiler_table import CompilerTable

########################################################################
# classes
########################################################################

class CompilationTest(compilation_test.CompilationTest):
    """A CompilationTest fetches compilation parameters from environment
    variables CPPFLAGS, _options, and _ldflags in addition
    to the CompilerTable-related parameters."""

    options = SetField(TextField(), computed="true")
    ldflags = SetField(TextField(), computed="true")
    source_files = SetField(TextField(), computed="true")
    executable = TextField(computed="true")
    language = TextField()


    def _GetCompilationSteps(self, c):

        lang = self.language
        compiler = c['CompilerTable.compilers'][lang]
        label_components = self.GetDatabase().GetLabelComponents(self.GetId())
        label_components[-1] = os.path.splitext(label_components[-1])[0]
        selector = '.'.join(label_components)
        path = c.GetDerivedValue(selector, lang + '_path')
        if path:
            compiler = Compiler(path, compiler.GetOptions(), compiler.GetLDFlags())
        options = (parse_string_list(c.GetDerivedValue(
            selector, 'CPPFLAGS', '')) +
                   parse_string_list(c.GetDerivedValue(
            selector, lang + '_options', '')))
        ldflags = (parse_string_list(c.GetDerivedValue(
            selector, lang + '_ldflags', '')))

        return [CompilationStep(compiler,
                                Compiler.MODE_LINK, self.source_files,
                                self.options + options,
                                self.ldflags + ldflags,
                                self.executable, [])]


class CompilationTestDatabase(Database):
    """A 'CompilationTestDatabase' test database maps source code files to
    compilation tests."""

    srcdir = TextField(title = "Source Directory",
                       description = "The root of the test suite's source tree.")
    excluded_subdirs = SetField(TextField(),
                                default_value = ['QMTest', 'CVS', '.svn', 'build'])
    test_extensions = DictionaryField(TextField(),
                                      EnumerationField(enumerals = ['c', 'cplusplus']),
                                      default_value = {'.c':'c',
                                                       '.cpp':'cplusplus',
                                                       '.cxx':'cplusplus',
                                                       '.cc':'cplusplus',
                                                       '.C':'cplusplus',
                                                       '.f':'fortran'})
    _is_generic_database = True
    

    def __init__(self, path, arguments):

        self.label_class = "file_label.FileLabel"
        self.modifiable = "false"
        # Initialize the base class.
        super(CompilationTestDatabase, self).__init__(path, **arguments)

        
    def GetSubdirectories(self, directory):

        dirname = os.path.join(self.srcdir, directory)
        return [subdir for subdir in dircache.listdir(dirname)
                if (os.path.isdir(os.path.join(dirname, subdir)) and
                    subdir not in self.excluded_subdirs)]


    def GetIds(self, kind, directory = '', scan_subdirs = 1):

        dirname = os.path.join(self.srcdir, directory)
        if not os.path.isdir(dirname):
            raise NoSuchSuiteError, directory

        if kind == Database.TEST:
            ids = [self.JoinLabels(directory, f)
                   for f in dircache.listdir(dirname)
                   if (os.path.isfile(os.path.join(dirname, f)) and
                       os.path.splitext(f)[1] in self.test_extensions)]

        elif kind == Database.RESOURCE:
            ids = []
            
        else: # SUITE
            ids = [self.JoinLabels(directory, d)
                   for d in self.GetSubdirectories(directory)
                   if d not in self.excluded_subdirs]

        if scan_subdirs:
            for subdir in dircache.listdir(dirname):
                if (subdir not in self.excluded_subdirs
                    and os.path.isdir(os.path.join(dirname, subdir))):
                    dir = self.JoinLabels(directory, subdir)
                    ids.extend(self.GetIds(kind, dir, True))

        return ids
    

    def GetExtension(self, id):

        if not id:
            return DirectorySuite(self, id)
            
        elif id == 'compiler_table':
            return CompilerTable({},
                                 qmtest_id = id,
                                 qmtest_database = self)

        id_components = self.GetLabelComponents(id)
        file_ext = os.path.splitext(id_components[-1])[1]
        if (file_ext in self.test_extensions and
            os.path.isfile(os.path.join(self.srcdir, id))):
            return self._MakeTest(id, self.test_extensions[file_ext])

        elif os.path.isdir(os.path.join(self.srcdir, id)):
            basename = os.path.basename(id)
            if not basename in self.excluded_subdirs:
                return DirectorySuite(self, id)

        else:
            return None


    def _MakeTest(self, test_id, language):


        src = os.path.abspath(os.path.join(self.srcdir, test_id))
        # Construct a unique name for the executable as it may be
        # kept for failure analysis.
        executable = os.path.splitext(os.path.basename(test_id))[0]
        if sys.platform == 'win32':
            executable += '.exe'

        resources = ['compiler_table']
        arguments = {}
        arguments['language'] = language
        arguments['source_files'] = [src]
        arguments['executable'] = executable
        arguments['resources'] = resources

        return CompilationTest(arguments,
                               qmtest_id = test_id,
                               qmtest_database = self)

qmtest-2.4.1/qm/test/classes/previous_testrun.py0000664000076400007640000000343011107032221021417 0ustar  stefanstefan########################################################################
#
# File:   previous_testrun.py
# Author: Stefan Seefeld
# Date:   2006-11-16
#
# Contents:
#   QMTest PreviousTestRun extension class.
#
# Copyright (c) 2006 by CodeSourcery, Inc.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

from qm.fields import TextField, PythonField
from qm.test.expectation_database import ExpectationDatabase
from qm.test.result import Result
from qm.test.base import load_results

########################################################################
# Classes
########################################################################

class PreviousTestRun(ExpectationDatabase):
    """A 'PreviousTestRun' uses test results as expectations.

    A 'PreviousTestRun' uses a ResultsFile such as generated by
    'qmtest run' to determine the expected outcome for the current
    test run."""

    file_name = TextField(description="The name of the results file.")
    results_file = PythonField("The results file.")


    def __init__(self, **args):

        super(PreviousTestRun, self).__init__(**args)
        if not self.results_file:
            self.results_file = open(self.file_name, "rb")
        results = load_results(self.results_file, self.test_database)
        self._results = {}
        for r in results:
            # Keep test results only.
            if r.GetKind() == Result.TEST:
                self._results[r.GetId()] = r

        
    def Lookup(self, test_id):

        return self._results.get(test_id) or Result(Result.TEST, test_id)
qmtest-2.4.1/qm/test/classes/file_label.py0000664000076400007640000000452211107032221020040 0ustar  stefanstefan########################################################################
#
# File:   file_label.py
# Author: Mark Mitchell
# Date:   06/11/2002
#
# Contents:
#   FileLabel
#
# Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
########################################################################

from   qm.label   import *
import os
import re

########################################################################
# Classes
########################################################################

class FileLabel(Label):
    """A 'FileLabel' is a 'Label' that uses the filesystem's naming scheme.

    A 'FileLabel' is a 'Label' whose separator character is the
    operating system's file system separator character (typically '/' or
    '\\').  These labels are not system-independent; there is no
    guarantee that 'FileLabel's will have the same meaning on different
    operating systems."""

    _sep = os.sep

    def Join(self, *labels):
        """Combine this label and the 'labels' into a single label.

        'labels' -- A sequence of strings giving the components of the
        new label.  All but the last are taken as directory names; the
        last is treated as a basename."""

        return self.__class__(apply(os.path.join, (self._label,) + labels))
    
        
    def Split(self):
        """Split the label into a pair '(directory, basename)'.

        returns -- A pair '(directory, basename)', each of which is
        a label.

        It is always true that 'directory.join(basename)' will return a
        label equivalent to the original label."""

        return os.path.split(self._label)


    def Basename(self):
        """Return the basename for the label.

        returns -- A string giving the basename for the label.  The
        value returned for 'l.basename()' is always the same as
        'l.split()[1]'."""

        return os.path.basename(self._label)
    
    
    def Dirname(self):
        """Return the directory name for the 'label'.

        returns -- A string giving the directory name for the 'label'.
        The value returned for 'l.dirname()' is always the same as
        'l.split()[0]'."""

        return os.path.dirname(self._label)
qmtest-2.4.1/qm/test/classes/local_host.py0000664000076400007640000000421311107032221020106 0ustar  stefanstefan########################################################################
#
# File:   local_host.py
# Author: Mark Mitchell
# Date:   2005-06-03
#
# Contents:
#   LocalHost
#
# Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
#######################################################################

import os
import os.path
from   qm.host import Host
import shutil

########################################################################
# Classes
#######################################################################

class LocalHost(Host):
    """A 'LocalHost' is the machine on which Python is running.

    The default directory for a 'LocalHost' is the current working
    directory for this Python process."""

    def UploadFile(self, local_file, remote_file = None):

        if remote_file is None:
            remote_file = os.path.basename(local_file)
        # Do not copy the files if they are the same.
        if not self._SameFile(local_file, remote_file):
            shutil.copy(local_file, remote_file)


    def UploadAndRun(self, path, arguments, environment = None,
                     timeout = -1):

        # There is no need to actually upload the file, since it is
        # running on the local machine.
        return self.Run(path, arguments, environment, timeout)


    def DownloadFile(self, remote_file, local_file = None):

        return self.UploadFile(remote_file, local_file)


    def _SameFile(self, file1, file2):
        """Return true iff 'file1' and 'file2' are the same file.

        returns -- True iff 'file1' and 'file2' are the same file,
        even if they have different names."""

        if not os.path.exists(file1) or not os.path.exists(file2):
            return False
        if hasattr(os.path, "samefile"):
            return os.path.samefile(file1, file2)
        return (os.path.normcase(os.path.abspath(file1))
                == os.path.normcase(os.path.abspath(file2)))


    def DeleteFile(self, remote_file):

        os.remove(remote_file)
qmtest-2.4.1/qm/test/classes/dir_run_database.py0000664000076400007640000000370111107032221021246 0ustar  stefanstefan########################################################################
#
# File:   dir_run_database.py
# Author: Mark Mitchell
# Date:   2005-08-08
#
# Contents:
#   QMTest DirRunDatabase class.
#
# Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

from glob import glob
import os.path
from qm.test import base
from qm.test.reader_test_run import ReaderTestRun
from qm.test.run_database import RunDatabase

########################################################################
# Classes
########################################################################

class DirRunDatabase(RunDatabase):
    """A 'DirRunDatabase' reads test runs from a directory.

    A 'DirRunDatabase' is associated with a given directory.  The
    database consists of all '.qmr' files in the directory.  Each
    '.qmr' file is treated as a result file."""

    def __init__(self, directory, database):
        """Create a new 'DirRunDatabase'.

        'directory' -- The path to the directory containing the
        results files.

        'database' -- The test 'Database' to which the results files
        correspond."""

        self.__runs = []
        # Read through all the .qmr files.
        for f in glob(os.path.join(directory, "*.qmr")):
            try:
                # Create the ResultReader corresponding to f.
                reader = base.load_results(f, database)
                run = ReaderTestRun(reader)
            except:
                # If anything goes wrong reading the file, just skip
                # it.
                continue
            # Add this run to the list.
            self.__runs.append(run)


    def GetAllRuns(self):

        return self.__runs
    
    
qmtest-2.4.1/qm/test/classes/simulator.py0000664000076400007640000000275511107032221020007 0ustar  stefanstefan########################################################################
#
# File:   simulator.py
# Author: Mark Mitchell
# Date:   2005-06-03
#
# Contents:
#   Simulator
#
# Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
#######################################################################

from local_host import LocalHost
from qm.fields import TextField, SetField

########################################################################
# Classes
#######################################################################

class Simulator(LocalHost):
    """A 'Simulator' is a semi-hosted simulation environment.

    The local file system is shared with the simulated machine.  A
    simulator is used to execute programs."""

    simulator = TextField(
        description = """The simulation program."""
        )

    # Any arguments that must be provided to the simulator.
    simulator_args = SetField(
        TextField(description = """Arguments to the simulation program."""))
    
    def Run(self, path, arguments, environment = None, timeout = -1):

        arguments = self.simulator_args + [path] + arguments
        return super(Simulator, self.Run(self.simulator,
                                         arguments,
                                         environment,
                                         timeout))
qmtest-2.4.1/qm/test/classes/text_result_stream.py0000664000076400007640000003743511107032221021730 0ustar  stefanstefan########################################################################
#
# File:   test_result_stream.py
# Author: Mark Mitchell
# Date:   2001-10-10
#
# Contents:
#   QMTest TextResultStream class.
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# imports
########################################################################

import qm.common
import qm.fields
from   qm.test.base import *
from   qm.test.result import *
from   qm.test.file_result_stream import FileResultStream

########################################################################
# classes
########################################################################

class TextResultStream(FileResultStream):
    """A 'TextResultStream' displays test results textually.

    A 'TextResultStream' displays information textually, in human
    readable form.  This 'ResultStream' is used when QMTest is run
    without a graphical user interface."""

    arguments = [
        qm.fields.EnumerationField(
            name = "format",
            title = "Format",
            description = """The output format used by this result stream.

            There are three sections to the output:

            (S) Summary statistics.

            (I) Individual test-by-test results.

            (U) Individual test-by-test results for tests with unexpected
                outcomes.

            For each of the sections of individual test-by-test results, the
            results can be shown either in one of three modes:

            (A) Show all annotations.

            (N) Show no annotations.

            (U) Show annotations only if the test has an unexpected outcome.

            In the "brief" format, results for all tests are shown as
            they execute, with unexpected results displayed in full
            detail, followed by a list of all the tests with
            unexpected results in full detail, followed by the summary
            information.  This format is useful for interactive use:
            the user can see that the tests are running as they go,
            can attempt to fix failures while letting the remainder of
            the tests run, and can easily see the summary of the
            results later if the window in which the run is occurring
            is left unattended.

            In the "batch" format, statistics are displayed first
            followed by full results for tests with unexpected
            outcomes.  The batch format is useful when QMTest is run
            in batch mode, such as from an overnight job.  The first
            few lines of the results (often presented by email) give
            an overview of the results; the remainder of the file
            gives details about any tests with unexpected outcomes.

            The "full" format is like "brief" except that all
            annotations are shown for tests as they are run.

            In the "stats" format only the summary statistics are
            displayed.""",
            enumerals = ["brief", "batch", "full", "stats"]),
        qm.fields.TextField(
            name = "statistics_format",
            title = "Statistics Format",
            verbatim = "true",
            multiline = "true",
            description = """The format string used to display statistics.

            The format string is an ordinary Python format string.
            The following fill-ins are available:

            'TOTAL' -- The total number of tests.

            'EXPECTED' -- The total number of tests that had an
            expected outcome.

            'EXPECTED_PERCENT' -- The percentage of tests with
            expected outcomes.

            'UNEXPECTED' -- The total number of tests that had an 
            unexpected outcome.

            For each outcome 'O', there are additional fill-ins:

            'O' -- The total number of tests with outcome 'O'.
            
            'O_PERCENT' -- The percentage of tests with outcome 'O' to
            total tests, as a floating point value.

            'O_UNEXPECTED' -- The total number of tests with an
            unexpected outcome of 'O'.

            'O_UNEXEPECTED_PERCENT' -- The ratio of tests without an
            unexpected outcome of 'O' to total tests, as a floating
            point value."""),
        ]
    
    def __init__(self, arguments = None, **args):
        """Construct a 'TextResultStream'.

        'args' -- As for 'Extension.__init__'."""

        # Initialize the base class.
        super(TextResultStream, self).__init__(arguments, **args)

        # Pick a default format.
        if not self.format:
            self.format = "batch"
            try:
                if self.file.isatty():
                    self.format = "brief"
            except:
                pass
            
        self.__first_test = 1
        # Keep track of tests and resources that had unexpected outcomes.
        self.__unexpected_test_results = []
        self.__unexpected_resource_results = []
        # And how many tests were run.
        self.__num_tests = 0
        # And how many tests there are with each outcome.
        self.__outcome_counts = {}
        for o in Result.outcomes:
            self.__outcome_counts[o] = 0
        # And how many unexpected tests there are with each outcome.
        self.__unexpected_outcome_counts = {}
        for o in Result.outcomes:
            self.__unexpected_outcome_counts[o] = 0


    def WriteResult(self, result):
        """Output a test or resource result.

        'result' -- A 'Result'."""

        # Record the results as they are received.
        if result.GetKind() == Result.TEST:
            # Remember how many tests we have processed.
            self.__num_tests += 1
            # Increment the outcome count.
            outcome = result.GetOutcome()
            self.__outcome_counts[outcome] += 1
            # Remember tests with unexpected results so that we can
            # display them at the end of the run.
            test_id = result.GetId()
            expected_outcome = self._GetExpectedOutcome(result.GetId())
            if self.format != "stats" and outcome != expected_outcome:
                self.__unexpected_outcome_counts[outcome] += 1
                self.__unexpected_test_results.append(result)
        else:
            if (self.format != "stats"
                and result.GetOutcome() != result.PASS):
                self.__unexpected_resource_results.append(result)
            
        # In some modes, no results are displayed as the tests are run.
        if self.format == "batch" or self.format == "stats":
            return
        
        # Display a heading before the first result.
        if self.__first_test:
            self._DisplayHeading("TEST RESULTS")
            self.__first_test = 0
        
        # Display the result.
        self._DisplayResult(result, self.format)

        # Display annotations associated with the test.
        if (self.format == "full"
            or (self.format == "brief"
                and result.GetOutcome() != Result.PASS)):
            self._DisplayAnnotations(result)


    def Summarize(self):
        """Output summary information about the results.

        When this method is called, the test run is complete.  Summary
        information should be displayed for the user, if appropriate.
        Any finalization, such as the closing of open files, should
        also be performed at this point."""

        if self.format == "batch":
            self._DisplayStatistics()

        # Show results for tests with unexpected outcomes.
        if self.format in ("full", "brief", "batch"):
            compare_ids = lambda r1, r2: cmp(r1.GetId(), r2.GetId())

            # Sort test results by ID.
            self.__unexpected_test_results.sort(compare_ids)
            # Print individual test results.
            if self.expected_outcomes:
                self._DisplayHeading("TESTS WITH UNEXPECTED OUTCOMES")
            else:
                self._DisplayHeading("TESTS THAT DID NOT PASS")
            self._SummarizeResults(self.__unexpected_test_results)

            if self.__unexpected_resource_results:
                # Sort resource results by ID.
                self.__unexpected_resource_results.sort(compare_ids)
                # Print individual resource results.
                self._DisplayHeading("RESOURCES THAT DID NOT PASS")
                self._SummarizeResults(self.__unexpected_resource_results)

        if self.format != "batch":
            self._DisplayStatistics()
        
        # Invoke the base class method.
        super(TextResultStream, self).Summarize()


    def _DisplayStatistics(self):
        """Write out statistical information about the results.

        Write out statistical information about the results."""

        # Summarize the test statistics.
        if self.statistics_format:
            self._FormatStatistics(self.statistics_format)
        elif self.expected_outcomes:
            self._SummarizeRelativeTestStats()
        else:
            self._SummarizeTestStats()


    def _SummarizeTestStats(self):
        """Generate statistics about the overall results."""

        # Print a header.
        self.file.write("\n")
        self._DisplayHeading("STATISTICS")

        # Build the format string.  If there are no tests we do not
        # provide any output.
        if self.__num_tests != 0:
            # Indicate the total number of tests.
            format = "  %(TOTAL)6d        tests total\n"
            # Include a line for each outcome.
            for o in Result.outcomes:
                if self.__outcome_counts[o] != 0:
                    format += ("  %%(%s)6d (%%(%s)3.0f%%%%) tests %s\n"
                               % (o, o + "_PERCENT", o))
            format += "\n"
        else:
            format = ""

        self._FormatStatistics(format)

        
    def _SummarizeRelativeTestStats(self):
        """Generate statistics showing results relative to expectations."""

        # Print a header.
        self.file.write("\n")
        self._DisplayHeading("STATISTICS")

        # Build the format string.  If there are no tests we do not
        # provide any output.
        if self.__num_tests != 0:
            # Indicate the total number of tests.
            format = ("  %(EXPECTED)6d (%(EXPECTED_PERCENT)3.0f%%) "
                      "tests as expected\n")
            # Include a line for each outcome.
            for o in Result.outcomes:
                if self.__unexpected_outcome_counts[o] != 0:
                    format += ("  %%(%s)6d (%%(%s)3.0f%%%%) tests "
                               "unexpected %s\n"
                               % (o + "_UNEXPECTED",
                                  o + "_UNEXPECTED_PERCENT",
                                  o))
            format += "\n"
        else:
            format = ""

        self._FormatStatistics(format)


    def _FormatStatistics(self, format):
        """Output statistical information.

        'format' -- A format string with (optional) fill-ins
        corresponding to statistical information.

        The formatted string is written to the result file."""

        # Build the dictionary of format fill-ins.
        num_tests = self.__num_tests
        unexpected = len(self.__unexpected_test_results)
        expected = num_tests - unexpected
        values = { "TOTAL" : num_tests,
                   "EXPECTED" : expected,
                   "UNEXPECTED" : unexpected }
        if num_tests:
            values["EXPECTED_PERCENT"] = (100. * expected) / num_tests
        else:
            values["EXPECTED_PERCENT"] = 0.0
        for o in Result.outcomes:
            count = self.__outcome_counts[o]
            values[o] = count
            if num_tests:
                values[o + "_PERCENT"] = (100. * count) / num_tests
            else:
                values[o + "_PERCENT"] = 0.0
            count = self.__unexpected_outcome_counts[o]
            values[o + "_UNEXPECTED"] = count
            if num_tests:
                values[o + "_UNEXPECTED_PERCENT"] = (100. * count) / num_tests
            else:
                values[o + "_UNEXPECTED_PERCENT"] = 0.0

        self.file.write(format % values)

        
    def _SummarizeResults(self, results):
        """Summarize each of the results.

        'results' -- The sequence of 'Result' objects to summarize."""

        if len(results) == 0:
            self.file.write("  None.\n\n")
            return

        # Generate them.
        for result in results:
            self._DisplayResult(result, self.format)
            if self.format == "batch":
                self._DisplayAnnotations(result)


    def _DisplayResult(self, result, format):
        """Display 'result'.

        'result' -- The 'Result' of a test or resource execution.

        'format' -- The format to use when displaying results."""

        id_ = result.GetId()
        kind = result.GetKind()
        outcome = result.GetOutcome()

        # Print the ID and outcome.
        if self.expected_outcomes:
            # If expected outcomes were specified, print the expected
            # outcome too.
            expected_outcome = \
                self.expected_outcomes.get(id_, Result.PASS)
            if (outcome == Result.PASS
                and expected_outcome == Result.FAIL):
                self._WriteOutcome(id_, kind, "XPASS")
            elif (outcome == Result.FAIL
                  and expected_outcome == Result.FAIL):
                self._WriteOutcome(id_, kind, "XFAIL")
            elif outcome != expected_outcome:
                self._WriteOutcome(id_, kind, outcome, expected_outcome)
            else:
                self._WriteOutcome(id_, kind, outcome)
        else:
            self._WriteOutcome(id_, kind, outcome)

        # Print the cause of the failure.
        cause = result.GetCause()
        if cause:
            cause = qm.common.html_to_text(cause)
            for l in cause.splitlines():
                self.file.write("    " + l + "\n")
            
        self.file.write('\n')


    def _DisplayAnnotations(self, result):
        """Display the annotations associated with 'result'.

        'result' -- The 'Result' to dispay."""

        keys = result.keys()
        keys.sort()
        for name in keys:
            # The CAUSE property has already been displayed."
            if name == Result.CAUSE:
                continue
            # Add an item to the list
            self.file.write("    %s:\n" % name)

            # Convert the HTML to text.
            text = qm.common.html_to_text(result[name])

            # Write out the text.
            for l in text.splitlines():
                self.file.write("      " + l + "\n")
            self.file.write("\n")
        

    def _WriteOutcome(self, name, kind, outcome, expected_outcome=None):
        """Write a line indicating the outcome of a test or resource.

        'name' -- The name of the test or resource.

        'kind' -- The kind of result being displayed.
        
        'outcome' -- A string giving the outcome.

        'expected_outcome' -- If not 'None', the expected outcome."""

        if kind == Result.RESOURCE_SETUP:
            name = "Setup " + name
        elif kind == Result.RESOURCE_CLEANUP:
            name = "Cleanup " + name
        
        if expected_outcome:
            self.file.write("  %-46s: %-8s, expected %-8s\n"
                            % (name, outcome, expected_outcome))
        else:
            self.file.write("  %-46s: %-8s\n" % (name, outcome))

            
    def _DisplayHeading(self, heading):
        """Display 'heading'.

        'heading' -- The string to use as a heading for the next
        section of the report."""

        self.file.write("--- %s %s\n\n" %
                        (heading, "-" * (73 - len(heading))))
qmtest-2.4.1/qm/test/classes/tet_stream.py0000664000076400007640000004466011107032221020140 0ustar  stefanstefan########################################################################
#
# File:   tet_stream.py
# Author: Nathaniel Smith
# Date:   2004-02-11
#
# Contents:
#   TETStream
#
# Copyright (c) 2004 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

from   dejagnu_test import DejaGNUTest
import qm.fields
import qm.common
from   qm.test.file_result_stream import FileResultStream
from   qm.test.result import Result
import time

########################################################################
# Classes
########################################################################

class TETStream(FileResultStream):
    """A 'TETStream' formats results as a TET journal.
    
    Provides special handling for 'DejaGNUTest' results.

    TET: http://tetworks.opengroup.org/
    TET journal format: see appendix C and D of
       http://tetworks.opengroup.org/documents/3.7/uguide.pdf

    For the meaning of TET result codes, we use as guidelines the LSB
    test faq, question Q1.11:
        * PASS - a test result belonging to this group is considered to
          be a pass for compliance testing purposes:
              o Pass - the test has been executed correctly and to
                completion without any kind of problem
              o Warning - the functionality is acceptable, but you
                should be aware that later revisions of the relevant
                standards or specification may change the requirements
                in this area.
              o FIP - additional information is provided which needs to
                be checked manually.
              o Unsupported - an optional feature is not available or
                not supported in the implementation under test.
              o Not in Use - some tests may not be required in certain
                test modes or when an interface can be implemented by a
                macro or function and there are two versions of the test
                only one is used.
              o Untested - no test written to check a particular feature
                or an optional facility needed to perform a test is not
                available on the system.
          [There are also "notimp" and "unapproved" cases mentioned in
          the LSB-FHS README, but they are otherwise undocumented, and
          don't correspond to any DejaGNU or QMTest outcomes anyway.]
        * FAIL - a test result belonging to this group is considered to
          be a fail for compliance testing purposes (unless the failure
          has been waived by an agreed Problem Report in the
          Certification Problem Reporting database):
              o Fail - the interface did not behave as expected.
              o Uninitiated - the particular test in question did not
                start to execute.
              o Unresolved - the test started but did not reach the
                point where the test was able to report success or
                failure.
              o Unreported - a major error occurred during the testset
                execution.  (The TET manual calls this NORESULT.)
    (From http://www.linuxbase.org/test/lsb-runtime-test-faq.html )
    
    DejaGNU test results are described as:
        * PASS - A test has succeeded.
        * FAIL - A test has produced the bug it was intended to
          capture.
        * WARNING - Declares detection of a minor error in the test case
          itself.  Use WARNING rather than ERROR for cases (such as
          communication failure to be followed by a retry) where the
          test case can recover from the error.  Note that sufficient
          warnings will cause a test to go from PASS/FAIL to
          UNRESOLVED.
        * ERROR - Declares a severe error in the testing framework
          itself.  An ERROR also causes a test to go from PASS/FAIL to
          UNRESOLVED.
        * UNRESOLVED - A test produced indeterminate results.  Usually,
          this means the test executed in an unexpected fashion; this
          outcome requires that a human being go over results, to
          determine if the test should have passed or failed.  This
          message is also used for any test that requires human
          intervention because it is beyond the abilities of the testing
          framework.  Any unresolved test should be resolved to PASS or
          FAIL before a test run can be considered finished.

          Examples:
              - a test's execution is interrupted
              - a test does not produce a clear result (because of
                WARNING or ERROR messages)
              - a test depends on a previous test case which failed
        * UNTESTED - a test case that isn't run for some technical
          reason.  (E.g., a dummy test created as a placeholder for a
          test that is not yet written.)
        * UNSUPPORTED - Declares that a test case depends on some
          facility that does not exist in the testing environment; the
          test is simply meaningless.
    (From a combination of DejaGNU manual sections "Core Internal
    Procedures", "C Unit Testing API", and "A POSIX conforming test
    framework".)

    """
    
    # TET result codes:
    PASS = (0, "PASS")
    WARNING = (101, "WARNING")
    FIP = (102, "FIP")
    UNSUPPORTED = (4, "UNSUPPORTED")
    NOTINUSE = (3, "NOTINUSE")
    UNTESTED = (5, "UNTESTED")

    FAIL = (1, "FAIL")
    UNINITIATED = (6, "UNINITIATED")
    UNRESOLVED = (2, "UNRESOLVED")
    UNREPORTED = (7, "UNREPORTED")


    def __init__(self, arguments = None, **args):

        super(TETStream, self).__init__(arguments, **args)
        
        self._start_time = ""
        self._finish_time = ""
        self._aborted = False
        self._username = ""
        self._userid = ""
        self._version = ""
        self._uname = ""
        self._cmdline = ""
        self._settings = {}

        self._tcc_number = 0
        self._printed_initial_stuff = False
            
            
    def _WriteLine(self, code, data, comment):
        """Write a line in TET journal format."""

        self.file.write("%i|%s|%s\n" % (code, data, comment))


    def _IsDejaGNUResult(self, result):
        """Returns 'True' if 'result' has DejaGNU subtests."""

        for key in result.keys():
            if key.startswith(DejaGNUTest.RESULT_PREFIX):
                return True
        return False


    def _TETFormatTime(self, time_string):
        """Converts an ISO-format date-time to a TET-format date-time.

        returns -- A 2-tuple whose first element is the time as a string,
        and whose second is the date as a string."""

        t = time.gmtime(qm.common.parse_time_iso(time_string))

        return (time.strftime("%H:%M:%S", t),
                time.strftime("%Y%m%d", t))


    def _ExtractTime(self, result, key):
        """Extracts the start time from a result."""

        if result.has_key(key):
            return self._TETFormatTime(result[key])[0]
        else:
            return "00:00:00"


    def WriteAnnotation(self, key, value):

        if key == "qmtest.run.start_time":
            self._start_time, self._start_date \
                              = self._TETFormatTime(value)
        elif key == "qmtest.run.end_time":
            self._finish_time, self._finish_data \
                               = self._TETFormatTime(value)
        elif key == "qmtest.run.aborted" and value == "true":
            self._aborted = True
        elif key == "qmtest.run.username":
            self._username = value
        elif key == "qmtest.run.userid":
            self._userid = value
        elif key == "qmtest.run.version":
            self._version = "qmtest-" + value
        elif key == "qmtest.run.uname":
            self._uname = value
        elif key == "qmtest.run.command_line":
            self._cmdline = value
        else:
            self._settings[key] = value


    def _WriteInitialStuff(self):
        """Print TET header information, but only on first call.

        Second and later calls are no-ops."""

        if self._printed_initial_stuff:
            return

        # Test case controller start
        # 0 | version time date | who
        # who is
        # "User:  () TCC Start, Command line: "
        data = "%s %s %s" % (self._version,
                             self._start_time,
                             self._start_date)
        who = "User: %s (%s) TCC Start, Command line: %s" \
              % (self._username, self._userid, self._cmdline)

        self._WriteLine(0, data, who)
        # Local system information
        # 5 | sysname nodename release version machine | text
        self._WriteLine(5, self._uname, "")
        # Local system configuration start
        # 20 | pathname mode | text
        self._WriteLine(20, "qmtest -1", "Config Start")
        for item in self._settings.iteritems():
            # Configuration variable setting
            # 30 || variable=value
            self._WriteLine(30, "", "%s=%s" % item)
        # Configuration end
        # 40 || text
        self._WriteLine(40, "", "Config End")
        
        self._printed_initial_stuff = True


    def WriteResult(self, result):

        self._WriteInitialStuff()
        if result.GetKind() == Result.TEST:
            self._tcc_number += 1
            if self._IsDejaGNUResult(result):
                self._WriteDejaGNUResult(result)
            else:
                self._WriteTestResult(result)
        else:
            # We have a resource result.
            self._WriteResourceResult(result)


    def _WriteTCStart(self, result):
        """Write a TET test case start line."""

        # Test case start
        # 10 | activity_number testcase_path time | invocable_components
        started = self._ExtractTime(result, Result.START_TIME)
        data = "%i %s %s" % (self._tcc_number,
                             "/" + result.GetId(),
                             started)
        self._WriteLine(10, data, "TC Start")


    def _WriteResultAnnotations(self, result, purpose,
                                num_restrict=None, seq_start=1):
        """Writes out annotations for a 'result' in TET format.

        Annotations are represented as (sequences of) "test case
        information" lines.

        'result' -- The 'Result' whose annotations should be written.

        'num_restrict' -- Only write out annotations that end with this
        number.  If the number is '1', also writes out all results that
        don't end in any number, with "INFO: " prefixed.  If 'None',
        writes out all annotations.

        'seq_start' -- The TET test case information sequence number to
        start with."""

        seqnum = seq_start
        keys = result.keys()
        keys.sort()
        for key in keys:
            value = result[key]
            prefix = ""
            if num_restrict is not None:
                if num_restrict == 1 and key[-1] not in "0123456789":
                    prefix = "INFO: "
                elif not key.endswith("_%i" % num_restrict):
                    continue
                    
            text = qm.common.html_to_text(value)
            for line in text.split("\n"):
                # Test case information
                # 520 | activity_num tp_num context block sequence | text
                #
                # We always set 'tp_num' to zero, because annotations
                #   for us are associated with test cases, not test
                #   purposes.
                # 'context' is to distinguish text coming from different
                #   subprocesses making up the test purpose; it's
                #   generally the pid.  For us, it's always zero.
                # 'block' is entirely undocumented, and the examples
                #   have it always set to one, so we simply set it to
                #   one as well.
                # 'sequence' appears to be incremented for each line
                #   within a single test purpose and context.
                self._WriteLine(520,
                                "%i %i 0 1 %i" % (self._tcc_number,
                                                  purpose,
                                                  seqnum),
                                "%s%s: %s" % (prefix, key, line))
                seqnum += 1


    def _WriteDejaGNUResult(self, result):
        """Write out a result that has DejaGNU subtest information."""

        self._WriteTCStart(result)
        
        # Get the DejaGNU annotations in sorted order.
        keys = filter(lambda k: k.startswith(DejaGNUTest.RESULT_PREFIX),
                      result.keys())
        keys.sort(lambda k1, k2: cmp(int(k1[len(DejaGNUTest.RESULT_PREFIX):]),
                                     int(k2[len(DejaGNUTest.RESULT_PREFIX):])))

        start_time = self._ExtractTime(result, Result.START_TIME)
        end_time = self._ExtractTime(result, Result.END_TIME)

        purpose = 1
        for k in keys:
            r = result[k]
            outcome = r[:r.find(":")]
            # Test purpose start
            # 200 | activity_number test_purpose_number time | text
            self._WriteLine(200,
                            "%i %i %s"
                            % (self._tcc_number, purpose, start_time),
                            "TP Start")

            outcome_num, outcome_name \
                = { DejaGNUTest.PASS: self.PASS,
                    DejaGNUTest.XPASS: self.PASS,
                    DejaGNUTest.FAIL: self.FAIL,
                    DejaGNUTest.XFAIL: self.FAIL,
                    DejaGNUTest.UNTESTED: self.UNTESTED,
                    DejaGNUTest.UNRESOLVED: self.UNRESOLVED,
                    DejaGNUTest.ERROR: self.UNRESOLVED,
                    DejaGNUTest.WARNING: self.WARNING,
                    # TET's UNSUPPORTED is like a FAIL for tests
                    # that check for optional features; UNTESTED is
                    # the correct correspondent for DejaGNU's
                    # UNSUPPORTED.
                    DejaGNUTest.UNSUPPORTED: self.UNTESTED,
                    }[outcome]
            # As a special case, check for magic annotation.
            if result.has_key("test_not_relevant_to_testing_mode"):
                outcome_num, outcome_name = self.NOTINUSE

            # Write per-purpose annotations:
            self._WriteResultAnnotations(result, purpose,
                                         num_restrict=purpose)

            # Test purpose result
            # 220 | activity_number tp_number result time | result-name
            data = "%i %i %i %s" % (self._tcc_number,
                                    purpose,
                                    outcome_num,
                                    end_time)
            self._WriteLine(220, data, outcome_name)

            purpose += 1
            
        # Test case end
        # 80 | activity_number completion_status time | text
        # "completion status" appears undocumented; it is zero in all of
        # the documented examples.
        self._WriteLine(80,
                        "%i 0 %s" % (self._tcc_number, end_time),
                        "TC End")

            
    def _WriteTestResult(self, result):
        """Write out a result that does not have DejaGNU annotations."""

        self._WriteTCStart(result)
        # Test purpose start
        # 200 | activity_number test_purpose_number time | text
        start_time = self._ExtractTime(result, Result.START_TIME)
        data = "%i 1 %s" % (self._tcc_number, start_time)
        self._WriteLine(200, data, "TP Start")

        outcome_num, outcome_name = { Result.FAIL: self.FAIL,
                                      Result.PASS: self.PASS,
                                      Result.UNTESTED: self.UNINITIATED,
                                      Result.ERROR: self.UNREPORTED,
                                    }[result.GetOutcome()]
        if result.GetOutcome() == Result.ERROR:
            # Test case information
            # 520 | activity_num tp_num context block sequence | text
            # (see _WriteResultAnnotations for details)
            self._WriteLine(520,
                            "%i 1 0 1 1" % self._tcc_number,
                            "QMTest ERROR in test " + result.GetId())
            self._WriteResultAnnotations(result, 1, seq_start=2)
        else:
            self._WriteResultAnnotations(result, 1)

        # Test purpose result
        # 220 | activity_number tp_number result time | result-name
        end_time = self._ExtractTime(result, Result.END_TIME)
        data = "%i 1 %i %s" % (self._tcc_number, outcome_num, end_time)
        self._WriteLine(220, data, outcome_name)

        # Test case end
        # 80 | activity_number completion_status time | text
        # "completion status" appears undocumented; it is zero in all of
        # the documented examples.
        self._WriteLine(80,
                        "%i 0 %s" % (self._tcc_number, end_time),
                        "TC End")


    def _WriteResourceResult(self, result):
        """Write out information on a resource result.

        TET has no concept of resources, so we ignore successful
        resources, and print out "test case controller messages" for
        ERRORs and FAILUREs."""

        if result.GetOutcome() in (Result.FAIL, Result.ERROR):
            if result.GetKind() == Result.RESOURCE_SETUP:
                verbing = "setting up"
            elif result.GetKind() == Result.RESOURCE_CLEANUP:
                verbing = "cleaning up"
            else:
                assert False, "Unexpected result kind"
            id = result.GetId()
            outcome = result.GetOutcome()
            # Test case controller message
            # 50 || text describing problem
            self._WriteLine(50, "", "Problem with %s resource %s: %s"
                                    % (verbing, id, outcome))

            for key, value in result.items():
                for line in value.split("\n"):
                    self._WriteLine(50, "", "%s: %s" % (key, line))


    def Summarize(self):

        self._WriteInitialStuff()
        
        if self._aborted:
            # User abort
            # 90 | time | text
            self._WriteLine(90, self._finish_time, "Aborted.")

        # Test case controller end
        # 900 | time | text
        self._WriteLine(900, self._finish_time, "Done.")
qmtest-2.4.1/qm/test/classes/mount_database.py0000664000076400007640000002141111107032221020744 0ustar  stefanstefan########################################################################
#
# File:   mount_database.py
# Author: Mark Mitchell
# Date:   03/19/2003
#
# Contents:
#   MountDatabase
#
# Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
########################################################################

import dircache
import os.path
from   qm.test.database import *
from   qm.test.suite import Suite
from   qm.fields import *
import qm.test.database

########################################################################
# Classes
########################################################################

class MountDatabase(Database):
    """A 'MountDatabase' contains other databases.

    Every contained database has a "mount point", which is a label
    giving the root of the database.  A test with the ID "x" in a
    database with a mount point of "y" has the ID "x.y" in the
    containing database.

    The contained databases are found by looking for subdirectories of
    the 'MountDatabase' directory.  Every immediate subdirectory which
    is itself a QMTest database is mounted; its mount point is the
    name of the subdirectory."""

    class MountedSuite(Suite):
        """A 'MountedSuite' is a suite from a mounted database."""

        def __init__(self, database, suite_id, joiner, suite):

            super(MountDatabase.MountedSuite, self).\
                __init__({},
                         qmtest_id = suite_id,
                         qmtest_database = database)
            self.__suite = suite
            self.__joiner = joiner


        def IsImplicit(self):

            return self.__suite.IsImplicit()

        
        def GetTestIds(self):

            return map(self.__joiner, self.__suite.GetTestIds())
                                                         

        def GetSuiteIds(self):

            return map(self.__joiner, self.__suite.GetSuiteIds())


    mounts = DictionaryField(key_field = TextField(),
                             value_field = TextField(),
                             description=\
                """Dictionary mapping mount points to (sub-)database paths.
                If empty, the database directory is scanned for subdirectories.""")


    def __init__(self, path, arguments):

        # The label class used by the MountDatabase is the label class
        # used by the databases it contains.  They must all use the
        # same label class.
        label_class = None
        implicit = False
        # Find the contained databases.
        self.mounts = arguments.pop('mounts', {})
        self._mounts = {}
        if not self.mounts:
            # Scan local directory.
            implicit = True
            self.mounts = dict([(d, os.path.join(path, d))
                                for d in dircache.listdir(path)])
        else:
            # Translate relative paths into absolute paths.
            tmp = {}
            for k,v in self.mounts.iteritems():
                tmp[k] = os.path.join(path, v)
            self.mounts = tmp
        # Now translate the value from path to database
        for k,v in self.mounts.iteritems():
            if is_database(v):
                db = load_database(v)
                self._mounts[k] = db
                if not label_class:
                    label_class = db.label_class
                elif label_class != db.label_class:
                    raise QMException, \
                          "mounted databases use differing label classes"
            elif not implicit:
                raise QMException, "%s does not contain a test database"%v
                                   
        # Initialize the base class.
        arguments["modifiable"] = "false"
        if label_class:
            arguments["label_class"] = label_class
            
        Database.__init__(self, path, arguments)


        
    def GetIds(self, kind, directory="", scan_subdirs=1):

        ids = []
        if directory == "" and kind == Database.SUITE:
                ids.extend(self._mounts.keys())
        if scan_subdirs:
            dirs = directory and [directory] or self._mounts.keys()
            for d in dirs:
                database, joiner, subdir = self._SelectDatabase(d)
                ids += [joiner(i) for i in database.GetIds(kind, subdir, 1)]
        return ids

    def GetTest(self, test_id):

        joiner, contained_test \
             = self._GetContainedItem(Database.TEST, test_id)

        # Remap the prerequisites.
        arguments = contained_test.GetArguments()
        prerequisites = contained_test.GetPrerequisites()
        if prerequisites:
            new_prerequisites = map(lambda p: (joiner(p[0]), p[1]),
                                    prerequisites.items())
            arguments[Test.PREREQUISITES_FIELD_ID] = new_prerequisites

        # Remap the resources.
        self._AdjustResources(joiner, arguments)

        return TestDescriptor(self,
                              test_id,
                              contained_test.GetClassName(),
                              arguments)
    

    def GetResource(self, resource_id):

        joiner, contained_resource \
             = self._GetContainedItem(Database.RESOURCE, resource_id)

        # Remap the resources.
        arguments = contained_resource.GetArguments()
        self._AdjustResources(joiner, arguments)

        return ResourceDescriptor(self, resource_id,
                                  contained_resource.GetClassName(),
                                  arguments)
    

    def GetSuite(self, suite_id):

        if suite_id == "":
            return Database.GetSuite(self, suite_id)

        joiner, contained_suite \
            = self._GetContainedItem(Database.SUITE, suite_id)
        test_ids = map(joiner, contained_suite.GetTestIds())
        suite_ids = map(joiner, contained_suite.GetSuiteIds())
        return MountDatabase.MountedSuite(self, suite_id,
                                          joiner,
                                          contained_suite)
    

    def GetSubdirectories(self, directory):

        if directory == "":
            return self._mounts.keys()
        database, joiner, dir = self._SelectDatabase(directory)
        return database.GetSubdirectories(dir)
        

    def GetClassPaths(self):

        paths = []
        for db in self._mounts.values():
            paths.extend(db.GetClassPaths())
            paths.append(get_configuration_directory(db.GetPath()))
        return paths


    def _AdjustResources(self, joiner, arguments):
        """Adjust the resource IDs stored in the 'arguments'.

        'joiner' -- A function of one argument which prepends the
        label for a mount point to the label it is given.

        'arguments' -- The arguments to a test or resource class.

        Modifies the arguments to contain resource names that are
        relative to the containing database."""
        
        resources = arguments.get(Runnable.RESOURCE_FIELD_ID)
        if resources:
            new_resources = map(joiner, resources)
            arguments[Runnable.RESOURCE_FIELD_ID] = new_resources
    

    def _GetContainedItem(self, kind, item_id):
        """Return 'item_id' from a mounted database.

        'kind' -- The kind of item to return.

        'item_id' -- The name of the item, in the containing
        database.

        returns -- A tuple '(joiner, item).  The 'item' will be from
        one of the mounted databases.  'joiner' is a function of one
        argument which prepends the mount point to its argument."""

        try:
            database, joiner, item_id = self._SelectDatabase(item_id)

            # Look for the item in the contained database.
            try:
                item = database.GetItem(kind, item_id)
            except NoSuchItemError, e:
                # Reset the id.
                e.item_id = joiner(item_id)
                raise

            return joiner, item
        except:
            raise Database._item_exceptions[kind](item_id)


    def _SelectDatabase(self, item_id):
        """Return the contained database in which 'item_id' can be found.

        'item_id' -- The name of an item in this database.

        returns -- A tuple '(database, joiner, id)' where 'database'
        is a 'Database', 'joiner' is a function of one argument which
        prepends the mount point to a label, and 'id' is the portion
        of 'item_id' that remains after stripping off the mount point
        of 'database'.  If 'item_id' does not correspond to any mount
        point, an exception is raised."""

        mount_point, item_id = self.SplitLabelLeft(item_id)
        db = self._mounts[mount_point]
        return (db, lambda p: self.JoinLabels(mount_point, p), item_id)
qmtest-2.4.1/qm/test/classes/explicit_suite.py0000664000076400007640000000334111107032221021012 0ustar  stefanstefan########################################################################
#
# File:   suite.py
# Author: Mark Mitchell
# Date:   1/02/2004
#
# Contents:
#   QMTest ExplicitSuite class
#
# Copyright (c) 2004 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

from   qm.fields import BooleanField, SetField, TextField
import qm.test.suite

########################################################################
# Classes
########################################################################

class ExplicitSuite(qm.test.suite.Suite):
    """An 'ExplicitSuite' stores all of the test and suite ids explicitly."""

    arguments = [
        SetField(
            TextField(
                name = "test_ids",
                title = "Test Names",
                description = """The the tests contained in this suite.""")),
        SetField(
            TextField(
                name = "suite_ids",
                title = "Suite Names",
                description = """The the suites contained in this suite.""")),
        BooleanField(name = "is_implicit",
                     title = "Implicit?",
                     description = """\
                     True if this test is implicitly generated by QMTest.""",
                     default_value = "false"),
        ]
    
    def IsImplicit(self):

        return self.is_implicit == "true"
   

    def GetTestIds(self):
      
        return self.test_ids

   
    def GetSuiteIds(self):
      
        return self.suite_ids
qmtest-2.4.1/qm/test/classes/python_label.py0000664000076400007640000000354311107032221020444 0ustar  stefanstefan########################################################################
#
# File:   python_label.py
# Author: Mark Mitchell
# Date:   06/11/2002
#
# Contents:
#   PythonLabel
#
# Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Imports
########################################################################

from   qm.label   import *
import re

########################################################################
# Classes
########################################################################

class PythonLabel(Label):
    """A 'PythonLabel' is a 'Label' that uses the 'a.b.c' naming scheme.

    A 'PythonLabel' is a 'Label' whose separator character is the period
    and whose components consist of lower-case letters, numerals, and
    underscores.  These labels have the property that they can be easily
    mapped to filenames on most operating systems; all valid labels are
    valid filenames (replacing '.' with '/') and two different labels
    will always map to two different filenames."""

    _sep = '.'
    """The separator character used to separate components."""

    __valid_label_regexp = re.compile("[-a-z0-9_%s]+$" % _sep)
    """A compiled regular expression that matches valid labels."""
    
    def IsValid(self, label, is_component):
        """Returns true if this label is not valid.

        returns -- True if this label is not valid."""

        if not Label.IsValid(self, label, is_component):
            # If the label does not meet the basic validity
            # requirements, reject it.
            return 0
        elif not self.__valid_label_regexp.match(label):
            # If the label contains invalid characters, reject it.
            return 0

        return 1


qmtest-2.4.1/qm/test/classes/sql_result_stream.py0000664000076400007640000001704511107032221021536 0ustar  stefanstefan########################################################################
#
# File:   sql_result_stream.py
# Author: Nathaniel Smith 
# Date:   2003-06-13
#
# Contents:
#   SQLResultStream, SQLResultSource
#
# Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

import qm.fields
from qm.extension          import Extension
from qm.test.result_stream import ResultStream
from qm.test.result_reader import ResultReader
from qm.db                 import quote_string, Connection
from qm.test.result        import Result

########################################################################
# Classes
########################################################################

class _SQLConnected(Extension):
    """Mixin class for classes that need a database connection."""

    arguments = [
        qm.fields.TextField(
            name = "db_name",
            title = "Database name",
            description = "The PostgreSQL database to connect to.",
            verbatim = "true",
            default_value = ""),
        qm.fields.TextField(
            name = "db_module",
            title = "Database module",
            description = "The DB 2.0 module to use.",
            verbatim = "true",
            default_value = "pgdb"),
        qm.fields.PythonField(
            name = "connection"),
    ]

    def __init__(self, arguments = None, **args):

        if arguments: args.update(arguments)
        super(_SQLConnected, self).__init__(**args)

        if not self.connection:
            self.connection = Connection(self.db_module,
                                         database=self.db_name)



class SQLResultStream(ResultStream, _SQLConnected):
    """A 'SQLResultStream' writes results out to an SQL database.
    
    This class currently supports PostgreSQL only."""


    def __init__(self, arguments = None, **args):

        super(SQLResultStream, self).__init__(arguments, **args)

        run_id_cursor = self.connection.execute("""
            SELECT nextval('run_id_seq');
            """)
        (self._run_id,) = run_id_cursor.fetchone()

        self.connection.execute("""
            INSERT INTO runs (run_id) VALUES (%i)
            """ % (self._run_id,))


    def WriteAnnotation(self, key, value):

        self.connection.execute("""
            INSERT INTO run_annotations (run_id, key, value)
            VALUES (%i, %s, %s)
            """ % (self._run_id,
                   quote_string(key),
                   quote_string(value)))
        

    def WriteResult(self, result):

        self.connection.execute("""
            INSERT INTO results (run_id, result_id, kind, outcome)
            VALUES (%i, %s, %s, %s)
            """ % (self._run_id,
                   quote_string(result.GetId()),
                   quote_string(result.GetKind()),
                   quote_string(result.GetOutcome())))

        for key, value in result.items():
            self.connection.execute("""
                INSERT INTO result_annotations (run_id,
                                                result_id,
                                                result_kind,
                                                key,
                                                value)
                VALUES (%i, %s, %s, %s, %s)
                """ % (self._run_id,
                       quote_string(result.GetId()),
                       quote_string(result.GetKind()),
                       quote_string(key),
                       quote_string(value)))


    def Summarize(self):

        self.connection.commit()



class _Buffer:
    """A little buffering iterator with one-element rewind."""

    def __init__(self, size, get_more):
        """Create a '_Buffer'.

        'size' -- the number of items to hold in the buffer at a time.

        'get_more' -- a function taking a number as its sole argument;
                      should return a list of that many new items (or as
                      many items are left, whichever is less).
        """

        self.size = size
        self.get_more = get_more
        self.buffer = get_more(size)
        self.idx = 0
        # Needed for rewinding over buffer refills:
        self.last = None


    def next(self):
        """Returns the next item, refilling the buffer if necessary."""

        idx = self.idx
        if idx == len(self.buffer):
            self.buffer = self.get_more(self.size)
            self.idx = 0
            idx = 0
        if not self.buffer:
            raise StopIteration
        self.idx += 1
        self.last = self.buffer[idx]
        return self.buffer[idx]


    def rewind(self):

        if self.idx == 0:
            self.buffer.insert(0, self.last)
        else:
            self.idx -= 1


    def __iter__(self):

        return self



class SQLResultReader(ResultReader, _SQLConnected):
    """A 'SQLResultReader' reads result in from an SQL database.

    This class currently supports PostgreSQL only."""

    arguments = [
        qm.fields.IntegerField(
            name = "run_id",
            title = "Run ID",
        ),
    ]

    def __init__(self, arguments = None, **args):

        super(SQLResultReader, self).__init__(arguments, **args)

        self._batch_size = 1000

        self._LoadAnnotations()
        self._SetupResultCursors()


    def _LoadAnnotations(self):

        cursor = self.connection.execute("""
            SELECT key, value FROM run_annotations
                              WHERE run_id = %i
            """ % (self.run_id))

        self._annotations = dict(iter(cursor.fetchone, None))


    def GetAnnotations(self):

        return self._annotations


    def _SetupResultCursors(self):
    
        # Set up our two result cursors.
        self.connection.execute("""
            DECLARE results_c CURSOR FOR
                SELECT result_id, kind, outcome FROM results
                                                WHERE run_id = %i
                ORDER BY result_id, kind
            """ % (self.run_id,))
        self.connection.execute("""
            DECLARE annote_c CURSOR FOR
                SELECT result_id, result_kind, key, value
                FROM result_annotations WHERE run_id = %i
                ORDER BY result_id, result_kind
            """ % (self.run_id,))

        def get_more_results(num):
            return self.connection.execute("""
                       FETCH FORWARD %i FROM results_c
                   """ % (num,)).fetchall()
        def get_more_annotations(num):
            return self.connection.execute("""
                       FETCH FORWARD %i FROM annote_c
                   """ % (num,)).fetchall()

        self._r_buffer = _Buffer(self._batch_size, get_more_results)
        self._a_buffer = _Buffer(self._batch_size, get_more_annotations)
        

    def GetResult(self):

        try:
            id, kind, outcome = self._r_buffer.next()
        except StopIteration:
            return None
        annotations = {}
        for result_id, result_kind, key, value in self._a_buffer:
            if (result_id, result_kind) != (id, kind):
                self._a_buffer.rewind()
                break
            annotations[key] = value
        return Result(kind, id, outcome, annotations)

########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/file.py0000664000076400007640000001274011107032221016702 0ustar  stefanstefan########################################################################
#
# File:   file.py
# Author: Alex Samuel
# Date:   2001-06-21
#
# Contents:
#   Test classes involving file contents.
#
# Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

"""File-related test classes."""

########################################################################
# imports
########################################################################

import qm.fields
import qm.test.base
from   qm.test.result import *
from   qm.test.test import *
import qm.web
import re
import string

########################################################################
# classes
########################################################################

class SubstitutionField(qm.fields.TupleField):
    """A rule for performing a text substitution.

    A 'SubstitutionField' consists of a regular expression pattern and a
    corresponding replacement string.  When the substitution is applied
    to a body of text, all substrings that match the pattern are
    replaced with the substitution string.

    The syntax for the regular expression and the substitution string is
    that of the standard Python 're' (regular expression) module."""

    def __init__(self, name, **properties):
        """Create a new 'SubstitutionField'.

        By default, the pattern and replacement string are empty."""

        # Initialize the base class.
        fields = (qm.fields.TextField(name = "pattern",
                                      title = "Pattern",),
                  qm.fields.TextField(name = "replacement",
                                      title = "Replacement"))
        qm.fields.TupleField.__init__(self, name, fields, **properties)


    def GetHelp(self):
        return """
        A substitution consists of a regular expression pattern and a
        substitution string.  When the substitution is applied, all
        subtrings matching the pattern are replaced with the
        substitution string.  The substitution string may reference
        matched groups in the pattern.

        The regular expression and substitution syntax are those of
        Python's standard "'re' regular expression module"."""



class FileContentsTest(Test):
    """Check that the contents of a file match the expected value.

    A 'FileContentsTest' examines the contents of a file.  The test
    passes if and only if the contents exactly match the expected value.

    The path to the file itself is not specified explicitly in the test.
    Instead, it is taken from a contex property; the name of that
    variable is specified in the **Path Property** field.

    Optionally, the test may specify one or more substitutions.  Each
    substitution consists of a regular expression pattern and a
    replacement string.  Both the actual file contents and the expected
    file contents are processed with these substitutions, with all
    pattern matches replaced with the corresponding substitutions,
    before the comparison is performed."""

    arguments = [
        qm.fields.TextField(
            name="path_property",
            title="Path Property",
            description="""The context property naming the file.

            The context property given here will contain the path name
            of the file.""",
            not_empty_text=1,
            default_value="path"),

        qm.fields.TextField(
            name="expected_contents",
            title="Expected Contents",
            description="""The expected contents of the file.""",
            verbatim="true",
            multiline="true",
            default_value=""),

        qm.fields.SetField(SubstitutionField(
            name="substitutions",
            title="Substitutions",
            description="""Regular expression substitutions.

            Each substitution will be applied to both the expected and
            actual contents of the file.  The comparison will be
            performed after the substitutions have been performed.

            You can use substitutions to ignore insignificant
            differences between the expected and autual contents."""))
        ]


    def Run(self, context, result):
        # Extract the path to the file we're testing.
        path = context[self.path_property]
        # Read the contents of the file.
        contents = open(path, "r").read()
        # Perform substitutions on the file contents.
        self.expected_contents = \
          self.__PerformSubstitutions(self.expected_contents)
        contents = self.__PerformSubstitutions(contents)
        # Compare the contents to the expected contents.
        if contents != self.expected_contents:
            result.Fail("Contents do not match expected contents.",
                        { "FileContentsTest.contents" : contents,
                          "FileContentsTest.expected_contents" :
                          self.expected_contents })


    def __PerformSubstitutions(self, text):
        """Perform substitutions on a body of text.

        returns -- The string 'text', processed with the substitutions
        configured for this test instance."""

        for pattern, replacement in self.substitutions:
            text = re.sub(pattern, replacement, text)
        return text



########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/xml_database.py0000664000076400007640000002744411107032221020416 0ustar  stefanstefan########################################################################
#
# File:   xml_database.py
# Author: Alex Samuel
# Date:   2001-03-08
#
# Contents:
#   XML-based test database implementation.
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# imports
########################################################################

import os
import qm.common
from   qm.extension import get_class_arguments
import qm.fields
import qm.label
import qm.structured_text
import qm.test.base
from   qm.test.database import *
from   qm.test.file_database import *
from   qm.test.suite import *
from   qm.test.classes.explicit_suite import ExplicitSuite
import qm.xmlutil
import shutil
import string
import xml
import xml.dom
import xml.sax

########################################################################
# classes
########################################################################

class TestFileError(RuntimeError):
    """An error in the format or contents of an XML test file."""

    pass



class XMLDatabase(ExtensionDatabase):
    """A database representing tests as XML files in a directory tree."""

    def __init__(self, path, arguments):

        # Initialize base classes.
        ExtensionDatabase.__init__(self, path, arguments)
        # Create an AttachmentStore for this database.
        self.__store = qm.attachment.FileAttachmentStore(path)


    def _GetTestFromPath(self, test_id, test_path):
        try:
            return self.__LoadItem(test_id, test_path,
                                   self.__ParseTestDocument)
        except Exception, exception:
            # Problem while parsing XML.
            message = qm.error("error loading xml test",
                               test_id=test_id,
                               message=str(exception))
            raise TestFileError, message
        

    def _GetResourceFromPath(self, resource_id, resource_path):
        try:
            return self.__LoadItem(resource_id, resource_path,
                                   self.__ParseResourceDocument)
        except Exception, exception:
            # Problem while parsing XML.
            message = qm.error("error loading xml resource",
                               resource_id=resource_id,
                               message=str(exception))
            raise TestFileError, message
        
    # Helper functions.

    def __StoreAttachments(self, item):
        """Store all attachments in 'item' in the attachment store.

        'item' -- A 'Test' or 'Resource'.  If any of its fields contain
        attachments, add them to the 'AttachmentStore'."""

        # Get all of the attachments associated with the new item.
        new_attachments = item.GetAttachments()

        # Remove old attachments that are not also among the new
        # attachments.
        store = self.GetAttachmentStore()
        try:
            old_item = self.GetItem(item.kind, item.GetId())
        except:
            old_item = None
        if old_item:
            old_attachments = old_item.GetItem().GetAttachments()
            for o in old_attachments:
                found = 0
                for n in new_attachments:
                    if (n.GetStore() == store
                        and n.GetFileName() == o.GetFileName()):
                        found = 1
                        break
                if not found:
                    store.Remove(o.GetLocation())

        # Put any new attachments into the attachment store.
        for a in new_attachments:
            if a.GetStore() != store:
                location = self.__MakeDataFilePath(item.GetId(),
                                                   a.GetFileName())
                a.Move(store, location)

         
    def __MakeDataFilePath(self, item_id, file_name):
        """Construct the path to an attachment data file.

        'item_id' -- The test or resource item of which the attachment
        is part.

        'file_name' -- The file name specified for the attachment."""
        
        # Convert the item's containing suite to a path.
        parent_suite_path \
            = os.path.dirname(self._GetPathFromLabel(item_id))
        # The relative part of the eventual full file name will be
        # the part after the parent_suite_path and the directory
        # name separator character(s).
        abs_len = len(parent_suite_path) + len(os.sep)
        
        # Construct a file name free of suspicious characters.
        base, extension = os.path.splitext(file_name)
        safe_file_name = qm.label.thunk(base) + extension

        data_file_path = os.path.join(parent_suite_path, safe_file_name)
        # Is the file name by itself OK in this directory?  It must not
        # have a file extension used by the XML database itself, and
        # there must be no other file with the same name there.
        if extension not in [self.GetTestExtension(),
                             self.GetSuiteExtension(),
                             self.GetResourceExtension()] \
           and not os.path.exists(data_file_path):
            return data_file_path[abs_len:]

        # No good.  Construct alternate names by appending numbers
        # incrementally.
        index = 0
        while 1:
            data_file_path = os.path.join(parent_suite_path,
                                          safe_file_name + ".%d" % index)
            if not os.path.exists(data_file_path):
                return data_file_path[abs_len:]
            index = index + 1


    def __LoadItem(self, item_id, path, document_parser):
        """Load an item (a test or resource) from an XML file.

        This function is used for logic common to tests and resources.

        'item_id' -- The ID of the item to get.

        'path' -- The path to the test or resource file.

        'document_parser' -- A function that takes an XML DOM document
        as its argument and returns the constructed item object."""

        # Load and parse the XML item representation.
        document = qm.xmlutil.load_xml_file(path)
        # Turn it into an object.
        item = document_parser(item_id, document)

        return item


    def __ParseTestDocument(self, test_id, document):
        """Return a test object constructed from a test document.

        'test_id' -- The test ID of the test.

        'document' -- A DOM document containing a single test element
        from which the test is constructed."""
        
        # Parse the DOM node.
        test_class, arguments \
            = (qm.extension.parse_dom_element
               (document.documentElement,
                lambda n : qm.test.base.get_test_class(n, self),
                self.__store))
        test_class_name = qm.extension.get_extension_class_name(test_class)
        # For backwards compatibility, look for "prerequisite" elements.
        for p in document.documentElement.getElementsByTagName("prerequisite"):
            if not arguments.has_key("prerequisites"):
                arguments["prerequisites"] = []
            arguments["prerequisites"].append((qm.xmlutil.get_dom_text(p),
                                               p.getAttribute("outcome")))
        # For backwards compatibility, look for "resource" elements.
        for r in document.documentElement.getElementsByTagName("resource"):
            if not arguments.has_key("resources"):
                arguments["resources"] = []
            arguments["resources"].append(qm.xmlutil.get_dom_text(r))
        # Construct a descriptor for it.
        test = TestDescriptor(self,
                              test_id,
                              test_class_name,
                              arguments)
        return test
        

    def __ParseResourceDocument(self, resource_id, document):
        """Return a resource object constructed from a resource document.

        'resource_id' -- The resource ID of the resource.

        'document' -- A DOM document node containing a single resource
        element from which the resource object is constructed."""

        # Parse the DOM node.
        resource_class, arguments \
            = (qm.extension.parse_dom_element
               (document.documentElement,
                lambda n : qm.test.base.get_resource_class(n, self)))
        resource_class_name \
            = qm.extension.get_extension_class_name(resource_class)
        # Construct a descriptor for it.
        resource = ResourceDescriptor(self,
                                      resource_id,
                                      resource_class_name,
                                      arguments)
        return resource
    

    def _GetSuiteFromPath(self, suite_id, path):
        """Load the test suite file at 'path' with suite ID 'suite_id'.

        returns -- A 'Suite' object."""

        # Make sure there is a file by that name.
        if not os.path.isfile(path):
            raise NoSuchSuiteError, "no suite file %s" % path
        # Load and parse the suite file.
        document = qm.xmlutil.load_xml_file(path)
        # For backwards compatibility, handle XML files using the
        # "suite" tag.  New databases will have Suite files using the
        # "extension" tag.
        suite = document.documentElement
        if suite.tagName == "suite":
            assert suite.tagName == "suite"
            # Extract the test and suite IDs.
            test_ids = qm.xmlutil.get_child_texts(suite, "test_id")
            suite_ids = qm.xmlutil.get_child_texts(suite, "suite_id")
            # Make sure they're all valid.
            for id_ in test_ids + suite_ids:
                if not self.IsValidLabel(id_, is_component = 0):
                    raise RuntimeError, qm.error("invalid id", id=id_)
            # Construct the suite.
            return ExplicitSuite({ "is_implicit" : "false",
                                   "test_ids" : test_ids,
                                   "suite_ids" : suite_ids },
                                 **{ ExplicitSuite.EXTRA_ID : suite_id,
                                     ExplicitSuite.EXTRA_DATABASE : self })
        else:
            # Load the extension.
            extension_class, arguments = \
                qm.extension.parse_dom_element(
                    suite,
                    lambda n: get_extension_class(n, "suite", self),
                    self.GetAttachmentStore())
            # Construct the actual instance.
            extras = { extension_class.EXTRA_ID : suite_id,
                       extension_class.EXTRA_DATABASE : self }
            return extension_class(arguments, **extras)


    def WriteExtension(self, id, extension):

        kind = extension.kind
        if kind in ("resource", "test"):
            self.__StoreAttachments(extension)
        # Figure out what path should be used to store the test.
        path = self._GetPath(kind, id)
        # If the file is in a new subdirectory, create it.
        containing_directory = os.path.dirname(path)
        if not os.path.isdir(containing_directory):
            os.makedirs(containing_directory)
        extension.Write(open(path, "w"))
        
                 
    def GetAttachmentStore(self):
        """Returns the 'AttachmentStore' associated with the database.

        returns -- The 'AttachmentStore' containing the attachments
        associated with tests and resources in this database."""

        return self.__store


    def _Trace(self, message,):
        """Write a trace 'message'.

        'message' -- A string to be output as a trace message."""

        tracer = qm.test.cmdline.get_qmtest().GetTracer()
        tracer.Write(message, "xmldb")


########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/command.py0000664000076400007640000004213011107032221017375 0ustar  stefanstefan########################################################################
#
# File:   command.py
# Author: Alex Samuel
# Date:   2001-03-24
#
# Contents:
#   Test classes for testing command-line programs.
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

import cPickle
import errno
import os
import qm.common
import qm.executable
import qm.fields
import qm.test.base
from   qm.test.test import Test
from   qm.test.result import Result
import string
import sys
import types

########################################################################
# Classes
########################################################################

class ExecTestBase(Test):
    """Check a program's output and exit code.

    An 'ExecTestBase' runs a program and compares its standard output,
    standard error, and exit code with expected values.  The program
    may be provided with command-line arguments and/or standard
    input.

    The test passes if the standard output, standard error, and
    exit code are identical to the expected values."""

    arguments = [
        qm.fields.TextField(
            name="stdin",
            title="Standard Input",
            verbatim="true",
            multiline="true",
            description="""The contents of the standard input stream.

            If this field is left blank, the standard input stream will
            contain no data."""
            ),

        qm.fields.SetField(qm.fields.TextField(
            name="environment",
            title="Environment",
            description="""Additional environment variables.

            By default, QMTest runs tests with the same environment that
            QMTest is running in.  If you run tests in parallel, or
            using a remote machine, the environment variables available
            will be dependent on the context in which the remote test
            is executing.

            You may add variables to the environment.  Each entry must
            be of the form 'VAR=VAL'.  The program will be run in an
            environment where the environment variable 'VAR' has the
            value 'VAL'.  If 'VAR' already had a value in the
            environment, it will be replaced with 'VAL'.

            In addition, QMTest automatically adds an environment
            variable corresponding to each context property.  The name
            of the environment variable is the name of the context
            property, prefixed with 'QMV_'.  For example, if the value
            of the context property named 'target' is available in the
            environment variable 'QMV_target'.  Any dots in the context
            key are replaced by a double-underscore; e.g.,
            "CompilerTable.c_path" will become
            "QMV_CompilerTable__c_path".""" )),
        
        qm.fields.IntegerField(
            name="exit_code",
            title="Exit Code",
            description="""The expected exit code.

            Most programs use a zero exit code to indicate success and a
            non-zero exit code to indicate failure."""
            ),

        qm.fields.TextField(
            name="stdout",
            title="Standard Output",
            verbatim="true",
            multiline="true",
            description="""The expected contents of the standard output stream.

            If the output written by the program does not match this
            value, the test will fail."""
            ),
        
        qm.fields.TextField(
            name="stderr",
            title="Standard Error",
            verbatim="true",
            multiline="true",
            description="""The expected contents of the standard error stream.

            If the output written by the program does not match this
            value, the test will fail."""
            ),

        qm.fields.IntegerField(
            name="timeout",
            title="Timeout",
            description="""The number of seconds the child program will run.

            If this field is non-negative, it indicates the number of
            seconds the child program will be permitted to run.  If this
            field is not present, or negative, the child program will be
            permitted to run for ever.""",
            default_value = -1,
            ),
        ]


    def MakeEnvironment(self, context):
        """Construct the environment for executing the target program."""

        # Start with any environment variables that are already present
        # in the environment.
        environment = os.environ.copy()
        # Copy context variables into the environment.
        for key, value in context.items():
            # If the value has unicode type, only transfer
            # it if it can be cast to str.
            if  isinstance(value, unicode):
                try:
                    value = str(value)
                except UnicodeEncodeError:
                    continue
            if  isinstance(value, str):
                name = "QMV_" + key.replace(".", "__")
                environment[name] = value
        # Extract additional environment variable assignments from the
        # 'Environment' field.
        for assignment in self.environment:
            if "=" in assignment:
                # Break the assignment at the first equals sign.
                variable, value = string.split(assignment, "=", 1)
                environment[variable] = value
            else:
                raise ValueError, \
                      qm.error("invalid environment assignment",
                               assignment=assignment)
        return environment


    def ValidateOutput(self, stdout, stderr, result):
        """Validate the output of the program.

        'stdout' -- A string containing the data written to the standard output
        stream.

        'stderr' -- A string containing the data written to the standard error
        stream.

        'result' -- A 'Result' object. It may be used to annotate
        the outcome according to the content of stderr.

        returns -- A list of strings giving causes of failure."""

        causes = []
        # Check to see if the standard output matches.
        if not self.__CompareText(stdout, self.stdout):
            causes.append("standard output") 
            result["ExecTest.expected_stdout"] = result.Quote(self.stdout)
        # Check to see if the standard error matches.
        if not self.__CompareText(stderr, self.stderr):
            causes.append("standard error")
            result["ExecTest.expected_stderr"] = result.Quote(self.stderr)

        return causes


    def RunProgram(self, program, arguments, context, result):
        """Run the 'program'.

        'program' -- The path to the program to run.

        'arguments' -- A list of the arguments to the program.  This
        list must contain a first argument corresponding to 'argv[0]'.

        'context' -- A 'Context' giving run-time parameters to the
        test.

        'result' -- A 'Result' object.  The outcome will be
        'Result.PASS' when this method is called.  The 'result' may be
        modified by this method to indicate outcomes other than
        'Result.PASS' or to add annotations."""

        # Construct the environment.
        environment = self.MakeEnvironment(context)
        # Create the executable.
        if self.timeout >= 0:
            timeout = self.timeout
        else:
            # If no timeout was specified, we sill run this process in a
            # separate process group and kill the entire process group
            # when the child is done executing.  That means that
            # orphaned child processes created by the test will be
            # cleaned up.
            timeout = -2
        e = qm.executable.Filter(self.stdin, timeout)
        # Run it.
        status = e.Run(arguments, environment, path = program)

        causes = []
        # Validate the exit status.
        if not result.CheckExitStatus('ExecTest.', 'Program',
                                      status, self.exit_code):
            causes.append("exit_code")
            result["ExecTest.expected_exit_code"] = str(self.exit_code)

        result["ExecTest.stdout"] = result.Quote(e.stdout)
        result["ExecTest.stderr"] = result.Quote(e.stderr)

        # Validate the output.
        causes += self.ValidateOutput(e.stdout, e.stderr, result)
        # If anything went wrong, the test failed.
        if causes:
            result.Fail("Unexpected %s." % string.join(causes, ", ")) 


    def __CompareText(self, s1, s2):
        """Compare 's1' and 's2', ignoring line endings.

        's1' -- A string.

        's2' -- A string.

        returns -- True if 's1' and 's2' are the same, ignoring
        differences in line endings."""

        # The "splitlines" method works independently of the line ending
        # convention in use.
        return s1.splitlines() == s2.splitlines()
        
    
class ExecTest(ExecTestBase):
    """Check a program's output and exit code.

    An 'ExecTest' runs a program by using the 'exec' system call."""

    arguments = [
        qm.fields.TextField(
            name="program",
            title="Program",
            not_empty_text=1,
            description="""The path to the program.

            This field indicates the path to the program.  If it is not
            an absolute path, the value of the 'PATH' environment
            variable will be used to search for the program."""
            ),
        
        qm.fields.SetField(qm.fields.TextField(
            name="arguments",
            title="Argument List",
            description="""The command-line arguments.

            If this field is left blank, the program is run without any
            arguments.

            An implicit 0th argument (the path to the program) is added
            automatically."""
            ))]

    _allow_arg_names_matching_class_vars = 1


    def Run(self, context, result):
        """Run the test.

        'context' -- A 'Context' giving run-time parameters to the
        test.

        'result' -- A 'Result' object.  The outcome will be
        'Result.PASS' when this method is called.  The 'result' may be
        modified by this method to indicate outcomes other than
        'Result.PASS' or to add annotations."""

        # Was the program not specified?
        if string.strip(self.program) == "":
            result.Fail("No program specified.")
            return

        self.RunProgram(self.program, 
                        [ self.program ] + self.arguments,
                        context, result)



class ShellCommandTest(ExecTestBase):
    """Check a shell command's output and exit code.

    A 'ShellCommandTest' runs the shell and compares its standard
    output, standard error, and exit code with expected values.  The
    shell may be provided with command-line arguments and/or standard
    input.

    QMTest determines which shell to use by the following method:

      - If the context contains the property
        'ShellCommandTest.command_shell', its value is split into
        an argument list and used.

      - Otherwise, if the '.qmrc' configuration file contains the common
        property 'command_shell', its value is split into an argument
        list and used.

      - Otherwise, the default shell for the target system is used.

    """

    arguments = [
        qm.fields.TextField(
            name="command",
            title="Command",
            description="""The arguments to the shell.

            This field contains the arguments that are passed to the
            shell.  It should not contain the path to the shell itself.

            If this field is left blank, the shell is run without
            arguments."""
            )
        ]

    
    def Run(self, context, result):
        """Run the test.

        'context' -- A 'Context' giving run-time parameters to the
        test.

        'result' -- A 'Result' object.  The outcome will be
        'Result.PASS' when this method is called.  The 'result' may be
        modified by this method to indicate outcomes other than
        'Result.PASS' or to add annotations."""

        # If the context specifies a shell, use it.
        if context.has_key("ShellCommandTest.command_shell"):
            # Split the context value to build the argument list.
            shell = qm.common.split_argument_list(
                context["ShellCommandTest.command_shell"])
        else:
            # Otherwise, use a platform-specific default.
            shell = qm.platform.get_shell_for_command()
        # Append the command at the end of the argument list.
        arguments = shell + [ self.command ]
        self.RunProgram(arguments[0], arguments, context, result)



class ShellScriptTest(ExecTestBase):
    """Check a shell script's output and exit code.

    A 'ShellScriptTest' runs the shell script provided and compares its
    standard output, standard error, and exit code with expected values.
    The shell script may be provided with command-line arguments and/or
    standard input.

    QMTest determines which shell to use by the following method:

      - If the context contains the property
        'ShellScriptTest.script_shell', its value is split into an
        argument list and used.

      - Otherwise, if the '.qmrc' configuration file contains the common
        property 'script_shell', its value is split into an argument
        list and used.

      - Otherwise, the default shell for the target system is used.

    """

    arguments = [
        qm.fields.TextField(
            name="script",
            title="Script",
            description="""The contents of the shell script.

            Provide the entire shell script here.  The script will be
            written to a temporary file before it is executed.  There
            does not need to be an explicit '#! /path/to/shell' at
            the beginning of the script because QMTest will not directly
            invoke the script.  Instead, it will run the shell, passing
            it the name of the temporary file containing the script as
            an argument.""",
            verbatim="true",
            multiline="true",
            ),
        qm.fields.SetField(qm.fields.TextField(
            name="arguments",
            title="Argument List",
            description="""The command-line arguments.

            If this field is left blank, the program is run without any
            arguments.

            An implicit 0th argument (the path to the program) is added
            automatically."""
            ))        
        ]

    _allow_arg_names_matching_class_vars = 1

    
    def Run(self, context, result):
        """Run the test.

        'context' -- A 'Context' giving run-time parameters to the
        test.

        'result' -- A 'Result' object.  The outcome will be
        'Result.PASS' when this method is called.  The 'result' may be
        modified by this method to indicate outcomes other than
        'Result.PASS' or to add annotations."""

        # On Windows, batch files must end with a ".bat" suffix or the
        # command shell will not execute them.
        if sys.platform == "win32":
            suffix = ".bat"
        else:
            suffix = ""
        # Create a temporary file for the script.
        self.__script_file_name, script_file \
            = qm.open_temporary_file("w+", suffix) 
        try:
            # Write the script to the temporary file.
            script_file.write(self.script)
            script_file.close()
            shell = self._GetShell(context)
            # Construct the argument list.  The argument list for the
            # interpreter is followed by the name of the script
            # temporary file, and then the arguments to the script.
            arguments = shell \
                        + [ self.__script_file_name ] \
                        + self.arguments
            self.RunProgram(arguments[0], arguments, context, result)
        finally:
            # Clean up the script file.
            os.remove(self.__script_file_name)


    def _GetShell(self, context):
        """Return the shell to use to run this test.

        'context' -- As for 'Test.Run'.
        
        returns -- A sequence of strings giving the path and arguments
        to be supplied to the shell.  The default implementation uses
        the value of the context property
        'ShellScriptTest.script_shell', or, if that is not defined, a
        platform-specific default."""
        
        # If the context specifies a shell, use it.
        if context.has_key("ShellScriptTest.script_shell"):
            # Split the context value to build the argument list.
            return qm.common.split_argument_list(
                context["ShellScriptTest.script_shell"])

        # Otherwise, use a platform-specific default.
        return qm.platform.get_shell_for_script()
        


########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/dejagnu_base.py0000664000076400007640000000425311107032221020372 0ustar  stefanstefan########################################################################
#
# File:   dejagnu_base.py
# Author: Mark Mitchell
# Date:   05/15/2003
#
# Contents:
#   DejaGNUBase
#
# Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

########################################################################
# Classes
########################################################################

class DejaGNUBase:
    """A 'DejaGNUBase' is a base class for tests and resources."""

    def _RecordCommand(self, result, command):
        """Record the execution of 'command'.

        'result' -- The 'Result' for the test.

        'command' -- A sequence of strings, giving the arguments to a
        command that is about to be executed.

        returns -- An integer giving the the index for this command.
        This value should be provided to '_RecordCommandOutput' after
        the command's output is known."""

        index = self.__next_command
        key = "DejaGNUTest.command_%d" % index
        result[key] = result.Quote(" ".join(command))
        self.__next_command += 1

        return index
        

    def _RecordCommandOutput(self, result, index, status, output):
        """Record the result of running a command.

        'result' -- The 'Result' for the test.
        
        'index' -- An integer, return from a previous call to
        '_RecordCommand'.
        
        'status' -- The exit status from the command.

        'output' -- A string containing the output, if any, from the
        command."""

        # Figure out what index to use for this output.
        
        if status != 0:
            result["DejaGNUTest.command_status_%d" % index] = str(status)
        if output:
            result["DejaGNUTest.command_output_%d" % index] \
              = result.Quote(output)


    def _SetUp(self, context):
        """Prepare to run a test.

        'context' -- The 'Context' in which this test will run.

        This method may be overridden by derived classes, but they
        must call this version."""

        # The next command will be the first.
        self.__next_command = 1
qmtest-2.4.1/qm/test/classes/temporary.py0000664000076400007640000000427611107032221020012 0ustar  stefanstefan########################################################################
#
# File:   temporary.py
# Author: Alex Samuel
# Date:   2001-04-06
#
# Contents:
#   Resource classes to manage temporary files and directories.
#
# Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# imports
########################################################################

import os
import qm.common
import qm.fields
from   qm.test.result import *
from   qm.test.test import *
from   qm.test.resource import *
import qm.temporary_directory

########################################################################
# classes
########################################################################

class TempDirectoryResource(Resource):
    """Resource class to manage a temporary directory.

    An instance of this resource creates a temporary directory during
    setup, and deletes it during cleanup.  The full path to the
    directory is available to tests via a context property."""

    arguments = [
        qm.fields.TextField(
            name="dir_path_property",
            title="Directory Path Property Name",
            description="The name of the context property which is "
            "set to the path to the temporary directory.",
            default_value="temp_dir_path"
            ),

        qm.fields.IntegerField(
            name="delete_recursively",
            title="Delete Directory Recursively",
            description="""This field is obsolete  All temporary
            directories are removed recursively.""",
            default_value=1,
            ),
        ]


    def SetUp(self, context, result):

        # Generate a temporary file name.
        self.__dir = qm.temporary_directory.TemporaryDirectory()
        context[self.dir_path_property] = self.__dir.GetPath()
    

    def CleanUp(self, result):

        del self.__dir


########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/classes/rsh_target.py0000664000076400007640000000670511107032221020131 0ustar  stefanstefan########################################################################
#
# File:   rsh_target.py
# Author: Mark Mitchell
# Date:   10/30/2001
#
# Contents:
#   RSHTarget
#
# Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

from   process_target import *
import string

########################################################################
# Classes
########################################################################

class RSHTarget(ProcessTarget):
    """A target that runs tests via a remote shell invocation.

    A 'RSHTarget' runs tests on a remote computer via a remote shell
    call.  The remote shell is in the style of 'rsh' and 'ssh'.  Using
    the remote shell, the target invokes the 'qmtest remote' script,
    which services commands sent via 'stdin', and replies via
    'stdout'."""

    host = qm.fields.TextField(
            title="Remote Host Name",
            description="""The name of the host on which to run tests.

            The name (or IP address) of the host on which QMTest
            should execute tests.  If this value is the empty string,
            the name of the target is used.""")
    remote_shell = qm.fields.TextField(
            title="Remote Shell Program",
            description="""The path to the remote shell program.

            The name of the program that can be used to create a
            remote shell.  This program must accept the same command
            line arguments as the 'rsh' program.""",
            default_value="ssh")
    arguments = qm.fields.TextField(
            title="Remote Shell Arguments",
            description="""The arguments to provide to the remote shell.

            A space-separated list of arguments to provide to the
            remote shell program.""",
            default_value="")
    

    
    def __init__(self, database, properties):
        """Construct a new 'RSHTarget'.

        'database' -- The 'Database' containing the tests that will be
        run.

        'properties'  -- A dictionary mapping strings (property names)
        to strings (property values)."""

        # Because "arguments" is both a field name and class variable,
        # the usual default handling of field arguments will not work
        # corectly; we must explicitly set the default value.
        if not properties.has_key("arguments"):
            properties["arguments"] = ""
            
        # Initialize the base class.
        ProcessTarget.__init__(self, database, properties)

        # Use the target name as the default name for the remote host.
        if not self.host:
            self.host = self.GetName()


    def _GetInterpreter(self):
        
        # Determine the remote shell program to use.
        remote_shell_program = self.remote_shell
        if not remote_shell_program:
            remote_shell_program = qm.rc.Get("remote_shell",
                                             default="ssh",
                                             section="common")
        # Extra command-line arguments to the remote shell program
        # may be specified with the "arguments" property.
        arguments = self.arguments.split()

        return [remote_shell_program] + arguments + [self.host]
qmtest-2.4.1/qm/test/classes/compiler_table.py0000664000076400007640000001217311107032221020744 0ustar  stefanstefan########################################################################
#
# File:   compiler_table.py
# Author: Mark Mitchell
# Date:   04/16/2003
#
# Contents:
#   CompilerTable
#
# Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved. 
#
########################################################################

"""Support for compiler test databases.

This module contains the 'CompilerTable' resource class which can be
used by compiler test databases to determine which compiler to test
based on context variables provided by the user."""

########################################################################
# Imports
########################################################################

import compiler
import qm
from   qm.test.database import get_database
from   qm.test.resource import Resource
from   local_host import LocalHost

########################################################################
# Classes
########################################################################

class CompilerTable(Resource):
    """A map from programming languages to 'Compiler's.

    The 'CompilerTable' resource uses the context to determine which
    compilers the user wants to test.  Test databases containing
    compiler tests should arrange for the tests they compain to depend
    on a 'CompilerTable' resource.

    The first context variable which is examined is
    'CompilerTable.languages'.  The value should be a
    whitespace-separated list of programming language names.  (See
    below for standardized names for some languages.)

    Then, for each language 'l' in the list of languages, the
    following context variables are examined:

    - 'CompilerTable.l_kind'

      The kind of compiler (e.g., "GCC" or "EDG") used to compile
      programs of language 'l'.  The 'kind' must name a class derived
      from 'Compiler'.

    - 'CompilerTable.l_path'

      The path to the compiler for language 'l'.  This path may be
      either absolute or relative.

    - 'CompilerTable.l_options'

      A whitespace-separated list of command-line options to provide
      to the compiler for language 'l'.  These options are passed to
      the constructor for the 'Compiler' object; generally, all tests
      are run with these options, followed by any test-specific
      options.  For example, if the user wants to test the compiler
      when run with '-O2', the user would put '-O2' in the 'l_options'
      context variable.

    The 'CompilerTable' resource provides the following context
    variables to all tests that depend upon the resource:

    - 'CompilerTable.compilers'

       The 'compilers' variable is a map from language names to
       instances of 'Compiler'.  Test classes should obtain the
       'Compiler' to use when compiling source files by using this
       map.

    - 'CompilerTable.target'

       An instance of 'Host' that can be used to run compiler
       programs."""

    LANG_C = "c"
    """The name of the C programming language."""
    
    LANG_CPLUSPLUS = "cplusplus"
    """The name of the C++ programming language."""
    
    def SetUp(self, context, result):

        # There are no compilers yet.
        compilers = {}
        
        # See what programming languages are supported.
        languages = context["CompilerTable.languages"].split()

        # For each language, create a Compiler.
        for l in languages:
            # Retrieve information from the context.
            kind = context["CompilerTable." + l + "_kind"].strip()
            path = context["CompilerTable." + l + "_path"].strip()
            # Look for (optional) command-line options.
            opts = context.get("CompilerTable." + l + "_options",
                               "").split()
            ldflags = context.get("CompilerTable." + l + "_ldflags",
                                  "").split()
            # Find the Python class corresponding to this compiler.
            compiler_class = compiler.__dict__[kind]
            # Instantiate the compiler.
            c = compiler_class(path, opts)
            c.SetLDFlags(ldflags)
            # Store it in the compilers map.
            compilers[l] = c
            
        # Make the table available to tests.
        context["CompilerTable.compilers"] = compilers

        # For backwards compatibility, we recognize this old
        # context variable here.
        interpreter = context.get("CompilerTest.interpreter")
        if interpreter:
            interpreter = interpreter.split()
            arguments = { simulator : interpreter[0],
                          simulator_args : interpreter[1:] }
            target = qm.test.classes.Simulator(arguments)
        else:
            target_desc = context.get("CompilerTable.target")
            if target_desc is None:
                target = LocalHost({})
            else:
                f = lambda n: qm.test.base.get_extension_class(n, "host",
                                                               get_database())
                host_class, arguments \
                    = qm.extension.parse_descriptor(target_desc.strip(), f)
                target = host_class(arguments)
        context["CompilerTable.target"] = target
qmtest-2.4.1/qm/test/execution_thread.py0000664000076400007640000001013411107032225017657 0ustar  stefanstefan########################################################################
#
# File:   execution_thread.py
# Author: Mark Mitchell
# Date:   2001-08-04
#
# Contents:
#   Code for coordinating the running of tests.
#
# Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# Imports
########################################################################

import os
import qm.common
from   qm.test.base import *
from   qm.test.context import *
from   qm.test.execution_engine import *
import qm.xmlutil
import Queue
from   result import *
import sys
from   threading import *

########################################################################
# Classes
########################################################################

class ExecutionThread(Thread, ExecutionEngine):
    """A 'ExecutionThread' executes tests in a separate thread.

    A 'ExecutionThread' is an 'ExecutionEngine' that runs tests in a
    separate thread.

    This class schedules the tests, plus the setup and cleanup of any
    resources they require, across one or more targets.

    The shedule is determined dynamically as the tests are executed
    based on which targets are idle and which are not.  Therefore, the
    testing load should be reasonably well balanced, even across a
    heterogeneous network of testing machines."""
    
    def __init__(self,
                 database,
                 test_ids,
                 context,
                 targets,
                 result_streams = None,
                 expectations = None):
        """Set up a test run.

        'database' -- The 'Database' containing the tests that will be
        run.
        
        'test_ids' -- A sequence of IDs of tests to run.  Where
        possible, the tests are started in the order specified.

        'context' -- The context object to use when running tests.

        'targets' -- A sequence of 'Target' objects, representing
        targets on which tests may be run.

        'result_streams' -- A sequence of 'ResultStream' objects.  Each
        stream will be provided with results as they are available.
        This thread will not perform any locking of these streams as
        they are written to; each stream must provide its own
        synchronization if it will be accessed before 'run' returns.

        'expectations' -- If not 'None', a dictionary mapping test IDs
        to expected outcomes."""

        Thread.__init__(self, None, None, None)
        ExecutionEngine.__init__(self, database, test_ids, context,
                                 targets, result_streams, expectations)

        # This is a deamon thread; if the main QMTest thread exits,
        # this thread should not prolong the life of the process.
        # Because the daemon flag is inherited from the creating thread,
        # threads created by the targets will automatically be daemon
        # threads.
        self.setDaemon(1)

        # Access to __terminated is guarded with this lock.
        self.__lock = Lock()


    def run(self):
        """Run the tests.

        This method runs the tests specified in the __init__
        function."""
        self.Run()


    def RequestTermination(self):
        """Request termination.

        Request that the execution thread be terminated.  This may
        take some time; tests that are already running will continue
        to run, for example."""

        self.__lock.acquire()
        ExecutionEngine.RequestTermination(self)
        self.__lock.release()


    def _IsTerminationRequested(self):
        """Returns true if termination has been requested.

        return -- True if Terminate has been called."""

        self.__lock.acquire()
        terminated = ExecutionEngine._IsTerminationRequested(self)
        self.__lock.release()
        return terminated

    
########################################################################
# Local Variables:
# mode: python
# indent-tabs-mode: nil
# fill-column: 72
# End:
qmtest-2.4.1/qm/test/web/0000775000076400007640000000000011122067201014530 5ustar  stefanstefanqmtest-2.4.1/qm/test/web/web.py0000664000076400007640000031001011107032225015653 0ustar  stefanstefan########################################################################
#
# File:   web.py
# Author: Alex Samuel
# Date:   2001-04-09
#
# Contents:
#   Common code for QMTest web user interface.
#
# Copyright (c) 2001 - 2005 by CodeSourcery, LLC.  All rights reserved. 
#
# For license terms see the file COPYING.
#
########################################################################

########################################################################
# imports
########################################################################

import os
import qm
import qm.attachment
import qm.common
from   qm.extension import *
import qm.fields
import qm.label
import qm.test.base
import qm.test.cmdline
from   qm.test.context import *
from   qm.test.database import *
from   qm.test.classes.previous_testrun import PreviousTestRun
from   qm.test.execution_thread import *
from   qm.test.result import *
from   qm.test.result_stream import *
from   qm.test.suite import *
import qm.web
import string
import StringIO
import sys
import time

########################################################################
# classes
########################################################################

class Item:
    """An 'Item' provides a convenient way to pass around named values.
    It is iterated over in listings generated by various dtml templates."""
    
    def __init__(self, id, **kwds):
        """Construct a new 'Item'.
        
        'id' -- The identifier.
        
        'kwds' -- A dictionary of named values to store."""
        
        self.id = id
        self.__dict__.update(kwds)


        
class DefaultDtmlPage(qm.web.DtmlPage):
    """Subclass of DTML page class for QMTest pages."""

    html_generator = "QMTest"

    NEGATIVE_UNEXPECTED = Result.FAIL
    """A test's result was unfavorably unexpected."""
    
    POSITIVE_UNEXPECTED = Result.PASS
    """A test's result was favorably unexpected."""
    
    EXPECTED = "EXPECTED"
    """A test's result was as expected."""

    EXPECTATION_KINDS \
        = [ NEGATIVE_UNEXPECTED, EXPECTED, POSITIVE_UNEXPECTED ]
    """The kinds of expectations."""
    
    outcomes = Result.outcomes + [EXPECTED]

    def __init__(self, dtml_template, server, **attributes):
        """Construct a new 'QMTestPage'.

        'server' -- The 'QMTestServer' creating this page.

        'dtml_template' -- The file name of the DTML template, relative
        to the DTML directory."""

        self.server = server
        
        # Set up the menus first; the attributes might override them.
        if not server.GetRunDatabase():
            if server.GetDatabase().IsModifiable():
                self.file_menu_items = [
                    ('New Test', "new-test"),
                    ('New Suite', "new-suite"),
                    ('New Resource', "new-resource"),
                    ]
            else:
                self.file_menu_items = [
                    ('New Test', ""),
                    ('New Suite', ""),
                    ('New Resource', ""),
                    ]
            self.file_menu_items.extend([
                ('Load Results', "javascript:load_results();"),
                ('Save Results', qm.test.cmdline.QMTest.results_file_name),
                ('Load Expectations', "javascript:load_expected_results();")])
            if self.HasModifiableExpectations():
                self.file_menu_items.extend([
                    ('Save Expectations',
                     qm.test.cmdline.QMTest.expectations_file_name)])
            else:
                self.file_menu_items.extend([('Save Expectations', "")])

            self.file_menu_items.extend([                
                ('Load Context', "javascript:load_context();"),
                ('Save Context', qm.test.cmdline.QMTest.context_file_name),
                ('Exit', 'shutdown')
                ])
            self.edit_menu_items = [
                ('Clear Results', "clear-results"),
                ('Edit Context', "edit-context"),
                ]
            self.run_menu_items = [
                ('All Tests', "run-tests")
                ]
            self.view_menu_items = [
                ('Directory', "dir"),
                ('Results', "show-results"),
                ('Report', "")
                ]
        else:
            
            self.file_menu_items = [
                ('New Test', ""),
                ('New Suite', ""),
                ('New Resource', ""),
                ('Load Results', ""),
                ('Save Results', ""),
                ('Load Expectations', ""),
                ('Save Expectations', ""),
                ('Load Context', ""),
                ('Save Context', ""),
                ('Exit', 'shutdown')
                ]
            self.edit_menu_items = [
                ('Clear Results', ""),
                ('Edit Context', ""),
                ]
            self.run_menu_items = [
                ('All Tests', "")
                ]
            self.view_menu_items = [
                ('Directory', "/test/dir"),
                ('Results', ""),
                ('Report', "/report/dir")
                ]

        self.help_menu_items = [
            ('Tutorial', "javascript:popup_tutorial();"),
            ('QMTest Web Site', "http://www.qmtest.com")
            ]

        qm.web.DtmlPage.__init__(self, dtml_template, **attributes)


    def GetName(self):
        """Return the name of the application."""

        return self.html_generator


    def MakeListingUrl(self):
        return qm.web.WebRequest("dir", base=self.request).AsUrl()


    def GetMainPageUrl(self):
        return self.MakeListingUrl()


    def GetDatabase(self):
        """Returns the 'Database' in use.

        returns -- The 'Database' in use."""

        return self.server.GetDatabase()


    def IsLabelInDirectory(self, id, directory):
        """Returns true if 'id' is in 'directory'.

        returns -- True if 'id' indicates a test contained in
        'directory', or one of its subdirectories."""

        while len(id) >= len(directory):
            if id == directory:
                return 1
            id = self.GetDatabase().SplitLabel(id)[0]
            
        return 0

        
    def FormatId(self, id, type, style="basic"):
        """Format 'id' as HTML.

        'id' -- The name of a test or resource.

        'type' -- The kind of item named by 'id'.  Either 'resource',
        'suite', or 'test'.

        'style' -- The formatting style to use.  One of 'plain',
        'basic', 'navigation', or 'tree'.

        returns -- A string containing HTML to use for 'id'."""
        
        script = "show-" + type
        request = qm.web.WebRequest(script, self.request, True, id=id)
        url = request.AsUrl()
        parent_suite_id, name = self.GetDatabase().SplitLabel(id)
        
        if style == "plain":
            return '%s' % id

        elif style == "basic":
            return '%s' % (url, id)

        elif style == "navigation":
            if parent_suite_id == "":
                parent = ""
            else:
                parent = self.FormatId(parent_suite_id, "dir", style)
                parent += id[len(parent_suite_id)]
            return parent \
                   + '%s' \
                   % (url, name)

        elif style == "tree":
            return '%s' \
                   % (url, name)

        assert None


    def GetResultsByOutcome(self, results):
        """Compute the tests in 'results' with each outcome.

        'results' -- A sequence of 'Result' instances.

        returns -- A dictionary mapping outcomes to the sequence of
        tests that have the indicated outcome in 'results'."""

        results_by_outcome = {}
        # At first, there are no results for any outcome.
        for o in self.outcomes:
            results_by_outcome[o] = []

        # Iterate through the results, adding each one to
        # 'results_by_outcome'.
        for r in results:
            results_by_outcome[r.GetOutcome()].append(r)

        return results_by_outcome


    def GetOutcomePercentages(self, results):
        """Compute the percentage (by outcome) of the 'results'.

        'results' -- A sequence of 'Result' instances.
        
        returns -- A dictionary mapping outcomes to the percentage (as
        a floating point number) of tests in 'results' that have
        that outcome."""

        # Compute the total number of tests for which results are
        # available.
        total = len(results)

        # Get the test results, organized by outcome.
        results = self.GetResultsByOutcome(results)

        # Compute the percentages.
        percentages = {}
        for o in self.outcomes:
            if total:
                percentages[o] = float(len(results[o])) / float(total)
            else:
                percentages[o] = 0.0

        return percentages    

    def HasModifiableExpectations(self):
        """Return True if expectations are modifiable."""

        return type(self.server.GetExpectationDatabase()) in (PreviousTestRun,)


class QMTestPage(DefaultDtmlPage):
    """A 'QMTestPage' is a 'DtmlPage' for pages generated by QMTest.

    A 'QMTestPage' automatically looks for DTML templates in the
    directory that contains QMTest DTML templates."""

    def __init__(self, dtml_template, server):
        """Construct a new 'QMTestPage'.

        'dtml_template' -- The file name of the DTML template, relative
        to the directory that contains QMTest DTML templates.  (Usually,
        this is just a basename.)

        'server' -- The 'QMTestServer' creating this page."""
        
        # Initialize the base class.
        DefaultDtmlPage.__init__(self,
                                 os.path.join("test", dtml_template),
                                 server)

        # Make the QMTest object available to the DTML pages.
        self.qmtest = qm.test.cmdline.get_qmtest()
        
        
    def GenerateStartBody(self, decorations=1):
        if decorations:
            # If the server is in the midst of executing tests, it
            # is not safe to edit tests, or to rerun the tests.
            if not self.server.GetResultsStream().IsFinished():
                # The basic edit menu items are OK.
                edit_menu_items = self.edit_menu_items[0:2]
                # The run model should have no options.
                run_menu_items = [
                    ('Stop Tests', "stop-tests")
                    ]
            # Otherwise, just use the values specified.
            else:
                edit_menu_items = self.edit_menu_items
                run_menu_items = self.run_menu_items

            # Figure out whether to use click-to-activate menus.
            click_menus = 0
            if qm.common.rc.has_option("common", "click_menus"):
                try:
                    click_menus = qm.common.rc.getboolean("common",
                                                          "click_menus")
                except ValueError:
                    pass
                
            # Generate the navigation bar.
            navigation_bar = \
              DefaultDtmlPage(os.path.join("test", "navigation-bar.dtml"),
                              self.server,
                              file_menu_items=self.file_menu_items,
                              edit_menu_items=edit_menu_items,
                              view_menu_items=self.view_menu_items,
                              run_menu_items=run_menu_items,
                              help_menu_items=self.help_menu_items,
                              click_menus = click_menus)
            return "%s
" % navigation_bar(self.request) else: return "" def IsFinished(self): """Return true iff no more results are forthcoming. returns -- True if no more tests are running.""" return 1 def GetRefreshDelay(self): """Returns the number of seconds to wait before refreshing the page. returns -- The number of seconds to wait before refreshing this page. A value of zero means that te page should never be refreshed. This function is only called if 'IsFinished' returns true.""" return 0 def GenerateHtmlHeader(self, description, headers=""): """Return the header for an HTML document. 'description' -- A string describing this page. 'headers' -- Any additional HTML headers to place in the '' section of the HTML document.""" # If the page isn't finished, automatically refresh it # every few seconds.y if not self.IsFinished(): headers = (headers + ('' % self.GetRefreshDelay())) return DefaultDtmlPage.GenerateHtmlHeader(self, description, headers) def GetExpectationUrl(self, id, expectation): """Return the URL for setting the expectation associated with 'id'. 'id' -- The name of a test. 'expectation' -- The current expectation associated with the test, or 'None' if there is no associated expectation.""" return qm.web.WebRequest("set-expectation", base=self.request, id=id, expectation=expectation or "None", url=self.request.AsUrl()).AsUrl() class QMTestReportPage(DefaultDtmlPage): """A 'QMTestReportPage' is a 'DtmlPage' for pages generated by QMTest. A 'QMTestReportPage' automatically looks for DTML templates in the directory that contains QMTest DTML templates.""" def __init__(self, dtml_template, server): """Construct a new 'QMTestReportPage'. 'dtml_template' -- The file name of the DTML template, relative to the directory that contains QMTest DTML templates. (Usually, this is just a basename.) 'server' -- The 'QMTestServer' creating this page.""" # Initialize the base class. DefaultDtmlPage.__init__(self, os.path.join("report", dtml_template), server) # Make the QMTest object available to the DTML pages. self.qmtest = qm.test.cmdline.get_qmtest() def GetRunDatabase(self): """Returns the 'RunDatabase' in use. returns -- The 'RunDatabase' in use.""" return self.server.GetRunDatabase() def GenerateStartBody(self, decorations=1): if decorations: edit_menu_items = self.edit_menu_items run_menu_items = self.run_menu_items # Figure out whether to use click-to-activate menus. click_menus = 0 if qm.common.rc.has_option("common", "click_menus"): try: click_menus = qm.common.rc.getboolean("common", "click_menus") except ValueError: pass # Generate the navigation bar. navigation_bar = \ DefaultDtmlPage(os.path.join("test", "navigation-bar.dtml"), self.server, file_menu_items=self.file_menu_items, edit_menu_items=edit_menu_items, view_menu_items=self.view_menu_items, run_menu_items=run_menu_items, help_menu_items=self.help_menu_items, click_menus = click_menus) return "%s
" % navigation_bar(self.request) else: return "" def GenerateHtmlHeader(self, description, headers=""): """Return the header for an HTML document. 'description' -- A string describing this page. 'headers' -- Any additional HTML headers to place in the '' section of the HTML document.""" return DefaultDtmlPage.GenerateHtmlHeader(self, description, headers) def GetResultURL(self, id, kind): """Generate a URL for the result page for 'id'. 'id' -- The name of a test or resource. 'kind' -- either 'test' or 'resource'. returns -- A url string for the result page for 'id'.""" row = self.request.get('row', 'qmtest.run.uname') script = {"test": "show-test", "resource": "show-resource"}[kind] request = qm.web.WebRequest(script, self.request, True, id=id, row=row) return request.AsUrl() def FormatTimeIso(self, time): return qm.common.format_time_iso(time) class ContextPage(QMTestPage): """DTML page for setting the context.""" def __init__(self, server): """Construct a new 'ContextPage'. 'server' -- The 'QMTestServer' creating this page.""" QMTestPage.__init__(self, "context.dtml", server) self.context = server.GetContext() class DirPage(QMTestPage): """A test database directory page. These attributes are available in DTML: 'path' -- The label directory that is being displayed. 'subdirs' -- A sequence of labels giving the subdirectories of this directory. 'test_ids' -- A sequence of labels giving the tests in this directory. 'suite_ids' -- A sequence of labels giving the suites in this directory. 'resource_ids' -- A sequence of labels giving the resources in this directory.""" SORT_NAME = 'name' """Sort by name.""" SORT_OUTCOME = 'outcome' """Sort by outcome.""" SORT_EXPECTATION = 'expectation' """Sort by expectation. In other words, put unexpected outcomes before expected outcomes.""" SORT_KINDS = [ SORT_NAME, SORT_OUTCOME, SORT_EXPECTATION ] """The kinds of sorting available.""" def __init__(self, server, path): """Construct a 'DirPage'. 'server' -- The 'QMTestServer' creating this page. 'path' -- The label directory to display.""" # Initialize the base class. QMTestPage.__init__(self, "dir.dtml", server) self.path = path self.database = server.GetDatabase() self.subdir_ids = self.database.GetSubdirectories(path) self.subdir_ids = map(lambda l: self.database.JoinLabels(path, l), self.subdir_ids) self.test_ids = self.database.GetTestIds(path, scan_subdirs=0) self.suite_ids = self.database.GetSuiteIds(path, scan_subdirs=0) # Do not show implicit suites. Otherwise, there are two # entries for a directory: one as a subdirectory entry, and # the other as a test suite. self.suite_ids = filter(lambda s, d=self.database: \ not d.GetSuite(s).IsImplicit(), self.suite_ids) self.resource_ids = self.database.GetResourceIds(path, scan_subdirs=0) # Get the results to date. results_stream = server.GetResultsStream() # It is important that we ask for IsFinished before asking # for GetTestResults. The stream could be finished between # the two calls, and it is better to show all the results but # claim they are incomplete than to show only some of the # results and claim they are complete. self.__is_finished = results_stream.IsFinished() self.test_results = results_stream.GetTestResults() self.expected_outcomes = server.GetExpectedOutcomes() self.expectation_is_modifiable = \ type(server.GetExpectationDatabase()) in (PreviousTestRun,) # Make it easy for the DTML page to get at all the outcomes. #self.outcomes = Result.outcomes + [self.EXPECTED] # Provide a menu choice to allow running all of the tests in # this directory. if self.server.GetRunDatabase(): self.run_menu_items.append(("This Directory", "")) else: self.run_menu_items.append(("This Directory", "javascript:run_dir();")) def GetRunUrl(self): """Return the URL for running this directory.""" return qm.web.WebRequest("run-tests", self.request, ids=self.path).AsUrl() def GetTestResultsForDirectory(self, directory): """Return all of the test results for tests in 'directory'. 'directory' -- A string giving the label for a directory. returns -- A sequence of 'Result' instances corresponding to results for tests from the indicated directory.""" # If we are in report mode, fetch the results from the run database. test_run = self.request.get('test_run') run_db = self.server.GetRunDatabase() if test_run and run_db: return run_db.GetAllRuns()[int(test_run)].GetAllResults(directory) # Else use the test_results. if directory == "": return self.test_results.values() else: return [r for r in self.test_results.values() if self.IsLabelInDirectory(r.GetId(), directory)] def GetUnexpectedResultsByOutcome(self, results): """Compute the tests in 'results' with each outcome. 'results' -- A sequence of 'Result' instances. returns -- A dictionary mapping outcomes to the results with that outcome -- and for which that outcome is unexpected. The (fake) outcome 'self.EXPECTED' is mapped to expected results.""" results_by_outcome = {} # At first, there are no results for any outcome. for o in self.outcomes: results_by_outcome[o] = [] for r in results: # See what outcome was expected. expectation = self.GetExpectation(r.GetId()) or Result.PASS # Update results_by_outcome. if r.GetOutcome() != expectation: results_by_outcome[r.GetOutcome()].append(r) else: results_by_outcome[self.EXPECTED].append(r) return results_by_outcome def GetUnexpectedOutcomePercentages(self, results): """Compute percentages of unexpected 'results'. 'results' -- A sequence of 'Result' instances. returns -- A dictionary mapping the 'EXPECTATION_KINDS' to the percentage (as a floating point number) of tests in 'results' that have that expectation.""" # Compute the total number of tests for which results are # available. total = len(results) # Get the test results, organized by outcome. results_by_outcome \ = self.GetUnexpectedResultsByOutcome(results) # Compute the absolute number of tests in each category. percentages = {} percentages[self.POSITIVE_UNEXPECTED] \ = len(results_by_outcome[Result.PASS]) percentages[self.NEGATIVE_UNEXPECTED] \ = (len(results_by_outcome[Result.FAIL]) + len(results_by_outcome[Result.ERROR]) + len(results_by_outcome[Result.UNTESTED])) percentages[self.EXPECTED] \ = len(results_by_outcome[self.EXPECTED]) # And the corresponding percentages. for e in self.EXPECTATION_KINDS: if percentages[e]: percentages[e] = float(percentages[e]) / float(total) else: percentages[e] = 0.0 return percentages def CountUnexpected(self, results): """Count the unexpected 'results'. 'results' -- A dictionary of the form returned by 'GetUnexpectedResultsByOutcome'. returns -- The total number of unexpected results.""" total = 0 # Go through all the outcomes except 'EXPECTED'. for o in Result.outcomes: total += len(results[o]) return total def GetResultURL(self, id, kind): """Generate a URL for the result page for 'id'. 'id' -- The name of a test or resource. 'kind' -- either 'test' or 'resource'. returns -- A url string for the result page for 'id'.""" script = {"test": "show-test", "resource": "show-resource"}[kind] request = qm.web.WebRequest(script, base=self.request, id=id) return request.AsUrl() def GetTests(self, sort): """Return information about all of the tests. 'sort' -- One of the 'SORT_KINDS' indicating how the results should be sorted. returns -- A sequence of 'Item' instances corresponding to all of the tests in this diretory.""" # There is no information yet. tests = [] # Iterate through each of the tests. for id in self.test_ids: outcome = self.GetTestOutcome(id) expectation = self.GetExpectation(id) tests.append(Item(id, outcome=outcome, expectation=expectation)) if sort == self.SORT_NAME: # The tests are already sorted by name. pass elif sort == self.SORT_OUTCOME: # Sort the test by outcome; interesting outcomes come first. buckets = {} for o in Result.outcomes + [None]: buckets[o] = [] # Go through the tests dropping each in the right bucket. for t in tests: buckets[t.outcome].append(t) # Combine the buckets. tests = [] for o in Result.outcomes + [None]: tests += buckets[o] elif sort == self.SORT_EXPECTATION: # Sort the test by expectations; unexpected outcomes come # first. buckets = {} for o in ['UNEXPECTED', self.EXPECTED, None]: buckets[o] = [] # Go through the tests dropping each in the right bucket. for t in tests: if (t.outcome == (t.expectation or Result.PASS)): buckets[self.EXPECTED].append(t) elif t.outcome: buckets['UNEXPECTED'].append(t) else: buckets[None].append(t) # Combine the buckets. tests = [] for o in ['UNEXPECTED', self.EXPECTED, None]: tests += buckets[o] else: # Ignore the sort request. (We cannot assert that this case # never happens because users can type any URL they like # into their web browser.) pass return tests def GetTestOutcome(self, test_id): """Return the 'Result' for 'test_id'. 'test_id' -- The name of the test whose result is requested. 'result' -- The result associated with the 'test_id', or 'None' if no result is available.""" test_run = self.request.get('test_run') run_db = self.server.GetRunDatabase() if test_run and run_db: result = run_db.GetAllRuns()[int(test_run)].GetResult(test_id) else: result = self.test_results.get(test_id) return result and result.GetOutcome() def GetDetailURL(self, test_id): """Return the detail URL for 'test_id'. 'test_id' -- The name of the test. returns -- The URL that contains details about the 'test_id'.""" return qm.web.WebRequest("show-result", self.request, True, id=test_id).AsUrl() def GetExpectation(self, test_id): """Return the expected outcome for 'test_id'. 'test_id' -- The name of the test. returns -- A string giving the expected outcome for 'test_id', or 'None' if there is no expectation.""" return self.expected_outcomes.get(test_id) def GetSortURL(self, sort): """Get the URL for this page, but sorted as indicated. 'sort' -- One of the 'SORT_KINDS'. returns -- A URL indicating this page, but sorted as indicated.""" return qm.web.WebRequest("show-dir", base=self.request, id=self.path, sort=sort).AsUrl() def IsFinished(self): """Return true iff no more results are forthcoming. returns -- True if no more tests are running.""" return self.__is_finished def GetRefreshDelay(self): """Returns the number of seconds to wait before refreshing the page. returns -- The number of seconds to wait before refreshing this page. A value of zero means that te page should never be refreshed. This function is only called if 'IsFinished' returns true.""" if len(self.test_results.items()) < 50: return 10 else: return 30 class DirReportPage(QMTestReportPage): """A run database directory page. These attributes are available in DTML: 'path' -- The label directory that is being displayed. 'subdirs' -- A sequence of labels giving the subdirectories of this directory. 'test_ids' -- A sequence of labels giving the tests in this directory. 'suite_ids' -- A sequence of labels giving the suites in this directory. 'resource_ids' -- A sequence of labels giving the resources in this directory.""" SORT_NAME = 'name' """Sort by name.""" SORT_OUTCOME = 'outcome' """Sort by outcome.""" SORT_EXPECTATION = 'expectation' """Sort by expectation. In other words, put unexpected outcomes before expected outcomes.""" SORT_KINDS = [ SORT_NAME, SORT_OUTCOME, SORT_EXPECTATION ] """The kinds of sorting available.""" def __init__(self, server, path): """Construct a 'DirPage'. 'server' -- The 'QMTestServer' creating this page. 'path' -- The label directory to display.""" # Initialize the base class. QMTestReportPage.__init__(self, "dir.dtml", server) self.path = path database = server.GetDatabase() self.database = database self.run_db = server.GetRunDatabase() self.subdir_ids = [database.JoinLabels(path, l) for l in database.GetSubdirectories(path)] self.test_ids = self.database.GetTestIds(path, scan_subdirs=0) self.suite_ids = [s for s in database.GetSuiteIds(path, scan_subdirs=0) if not database.GetSuite(s).IsImplicit()] self.resource_ids = self.database.GetResourceIds(path, scan_subdirs=0) def GetItems(self, kind = Result.TEST): """Return information about all of the items. returns -- A sequence of 'Item' instances corresponding to all of the tests in this diretory.""" # There is no information yet. items = [] # Iterate through each of the tests. test_runs = len(self.run_db.GetAllRuns()) for id in self.test_ids: outcomes = self.run_db.GetOutcomes(id, kind) if outcomes[Result.PASS] == test_runs: outcome = Result.PASS outcome_class = 'qmtest_pass' elif outcomes[Result.FAIL] == test_runs: outcome = Result.FAIL outcome_class = 'qmtest_fail' elif outcomes[Result.UNTESTED] == test_runs: outcome = Result.UNTESTED outcome_class = 'qmtest_untested' elif outcomes[Result.ERROR] == test_runs: outcome = Result.ERROR outcome_class = 'qmtest_error' else: outcome = 'MIXED' outcome_class = 'qmtest_mixed' # FIXME: add more detail here items.append(Item(id, outcome=outcome, outcome_class=outcome_class)) return items def MakeTestRunUrl(self, test_run): """Return the URL for navigating a particular test run.""" return qm.web.WebRequest("/test/dir", self.request, True, test_run=test_run, id=self.path).AsUrl() class ShowItemReportPage(QMTestReportPage): """DTML page for showing tests and resources.""" def __init__(self, server, item, type, field_errors={}): """Construct a new DTML context. These parameters are also available in DTML under the same name: 'server' -- The 'QMTestServer' creating this page. 'item' -- The 'TestDescriptor' or 'ResourceDescriptor' for the test being shown. 'type' -- Either "test" or "resource". 'field_errors' -- A map from field names to corresponding error messages.""" # Initialize the base class. QMTestReportPage.__init__(self, "show.dtml", server) self.item = item self.fields = item.GetClassArguments() assert type in ["test", "resource"] self.type = type self.field_errors = field_errors def GetTitle(self): """Return the page title for this page.""" url = self.request.GetScriptName() title = {"show-test": "Show Test Report ", "show-resource": "Show Resource Report "}[url] return title + self.item.GetId() def FormatFieldValue(self, field): """Return an HTML rendering of the value for 'field'.""" # Extract the field value. arguments = self.item.GetArguments() field_name = field.GetName() try: value = arguments[field_name] except KeyError: # Use the default value if none is provided. value = field.GetDefaultValue() return field.FormatValueAsHtml(self.server, value, "full") def GetClassDescription(self): """Return a full description of the test or resource class. returns -- The description, formatted as HTML.""" d = qm.extension.get_class_description(self.item.GetClass()) return qm.web.format_structured_text(d) def GetBriefClassDescription(self): """Return a brief description of the test or resource class. returns -- The brief description, formatted as HTML.""" d = qm.extension.get_class_description(self.item.GetClass(), brief=1) return qm.web.format_structured_text(d) def MakeShowUrl(self): """Return the URL for showing this item.""" return qm.web.WebRequest("show-" + self.type, self.request, True, id=self.item.GetId()).AsUrl() def GetDetailUrl(self, test_run): """Return the detail URL for a test. 'test_id' -- The name of the test. returns -- The URL that contains details about the 'test_id'.""" return qm.web.WebRequest("show-result", self.request, True, id=self.item.GetId(), test_run=test_run).AsUrl() def GetResults(self, key=None): """Return the results from all runs that correpond to the current id.""" result_set = [] test_runs = self.server.GetRunDatabase().GetAllRuns() for r in range(len(test_runs)): k = test_runs[r].GetAnnotation(key or self.request['row']) result = None try: result = test_runs[r].GetResult(self.item.GetId(), self.type) except KeyError: pass result_set.append(Item(k, test_run=r, result=result)) return result_set class LoadContextPage(QMTestPage): """DTML page for uploading a context.""" title = "Load Context" """The title for the page.""" heading = "Load the context from a file." """The heading printed across the top of the page.""" prompt = "The file from which to load the context." """The prompt for the file name.""" submit_url = "submit-context-file" """The URL to which the file should be submitted.""" def __init__(self, server): """Construct a new 'LoadContextPage'. 'server' -- The 'QMTestServer' creating this page.""" QMTestPage.__init__(self, "load.dtml", server) class LoadExpectationsPage(QMTestPage): """DTML page for uploading a context.""" title = "Load Expectations" """The title for the page.""" heading = "Load expectations from a file." """The heading printed across the top of the page.""" prompt = "The file from which to load expectations.""" """The prompt for the file name.""" submit_url = "submit-expectations" """The URL to which the file should be submitted.""" def __init__(self, server): """Construct a new 'LoadExpectationsPage'. 'server' -- The 'QMTestServer' creating this page.""" QMTestPage.__init__(self, "load.dtml", server) class LoadResultsPage(QMTestPage): """DTML page for uploading a context.""" title = "Load Results" """The title for the page.""" heading = "Load results from a file." """The heading printed across the top of the page.""" prompt = "The file from which to load the results.""" """The prompt for the file name.""" submit_url = "submit-results" """The URL to which the file should be submitted.""" def __init__(self, server): """Construct a new 'LoadContextPage'. 'server' -- The 'QMTestServer' creating this page.""" QMTestPage.__init__(self, "load.dtml", server) class NewItemPage(QMTestPage): """Page for creating a new test or resource.""" def __init__(self, server, type, item_id="", class_name="", field_errors={}): """Create a new DTML context. 'type' -- Either "test" or "resource". 'server' -- The 'QMTestServer' creating this page. 'item_id' -- The item ID to show. 'class_name' -- The class name to show. 'field_errors' -- A mapping of error messages for fields. Keys may be "_id" or "_class".""" # Initialize the base class. QMTestPage.__init__(self, "new.dtml", server) # Set up attributes. assert type in ["test", "resource"] self.database = server.GetDatabase() self.type = type self.item_id = item_id self.class_name = class_name if type == "test": self.class_names = self.database.GetTestClassNames() elif type == "resource": self.class_names = self.database.GetResourceClassNames() self.field_errors = field_errors def GetTitle(self): """Return the title this page.""" return "Create a New %s" % string.capwords(self.type) def GetClassDescriptions(self): """Return a description of the available classes. returns -- Structured text describing each of the available test or resource classes.""" desc = "**Available Classes**\n\n" for n in self.class_names: c = qm.test.base.get_extension_class(n, self.type, self.database) d = qm.extension.get_class_description(c, brief=1) desc = desc + " * " + n + "\n\n " + d + "\n\n" return desc def MakeSubmitUrl(self): """Return the URL for submitting the form. The URL is for the script 'create-test' or 'create-resource' as appropriate.""" return qm.web.WebRequest("create-" + self.type, base=self.request).AsUrl() class NewSuitePage(QMTestPage): """Page for creating a new test suite.""" def __init__(self, server, suite_id="", field_errors={}): """Create a new DTML context. 'server' -- The 'QMTestServer' creating this page. 'suite_id' -- Initial value for the new test suite ID field. 'field_errors' -- A mapping of error messages to fields. If empty, there are no errors.""" # Initialize the base class. QMTestPage.__init__(self, "new-suite.dtml", server) # Set up attributes. self.suite_id = suite_id self.field_errors = field_errors class ResultPage(QMTestPage): """DTML page for showing result detail.""" def __init__(self, server, result): """Construct a new 'ResultPage' 'server' -- The 'QMTestServer' creating this page. 'result' -- The result to display.""" QMTestPage.__init__(self, "result.dtml", server) self.result = result if result.GetKind() == Result.TEST: self.run_menu_items.append(("This Test", "javascript:run_test();")) def GetResultURL(self, id): return qm.web.WebRequest("show-result", base = self.request, id = id).AsUrl() def GetRunURL(self): return qm.web.WebRequest("run-tests", base = self.request, ids = self.result.GetId()).AsUrl() class SetExpectationPage(QMTestPage): """DTML page for setting the expectation associated with a test.""" def __init__(self, server, id): """Construct a new 'SetExpectationPage'. 'server' -- The 'QMTestServer' creating this page. 'id' -- The name of the test whose expectation is being set.""" QMTestPage.__init__(self, "set-expectation.dtml", server) self.outcomes = ["None"] + Result.outcomes class ShowItemPage(QMTestPage): """DTML page for showing and editing tests and resources.""" def __init__(self, server, item, edit, new, type, field_errors={}): """Construct a new DTML context. These parameters are also available in DTML under the same name: 'server' -- The 'QMTestServer' creating this page. 'item' -- The 'TestDescriptor' or 'ResourceDescriptor' for the test being shown. 'edit' -- True for editing the item; false for displaying it only. 'new' -- True for editing a newly-created item ('edit' is then also true). 'type' -- Either "test" or "resource". 'field_errors' -- A map from field names to corresponding error messages.""" # Initialize the base class. QMTestPage.__init__(self, "show.dtml", server) # Set up attributes. self.__database = server.GetDatabase() self.item = item self.fields = item.GetClassArguments() self.edit = edit self.new = new assert type in ["test", "resource"] self.type = type self.field_errors = field_errors if self.__database.IsModifiable(): self.edit_menu_items.append(("Edit %s" % string.capitalize(type), "javascript:edit_item();")) self.edit_menu_items.append(("Delete %s" % string.capitalize(type), "javascript:delete_item();")) if type == "test" and not edit: self.run_menu_items.append(("This Test", "javascript:run_test();")) def GetTitle(self): """Return the page title for this page.""" # Map the scriptname to a nicely-formatted title. url = self.request.GetScriptName() title = { "show-test": "Show Test", "edit-test": "Edit Test", "create-test": "New Test", "show-resource": "Show Resource", "edit-resource": "Edit Resource", "create-resource": "New Resource", }[url] # Show the item's ID too. title = title + " " + self.item.GetId() return title def FormatFieldValue(self, field): """Return an HTML rendering of the value for 'field'.""" # Extract the field value. arguments = self.item.GetArguments() field_name = field.GetName() try: value = arguments[field_name] except KeyError: # Use the default value if none is provided. value = field.GetDefaultValue() # Format it appropriately. server = self.server if self.edit: if field.IsHidden(): return field.FormatValueAsHtml(server, value, "hidden") elif field.IsReadOnly(): # For read-only fields, we still need a form input, but # the user shouldn't be able to change anything. Use a # hidden input, and display the contents as if this # wasn't an editing form. return field.FormatValueAsHtml(server, value, "hidden") \ + field.FormatValueAsHtml(server, value, "full") else: return field.FormatValueAsHtml(server, value, "edit") else: return field.FormatValueAsHtml(server, value, "full") def GetClassDescription(self): """Return a full description of the test or resource class. returns -- The description, formatted as HTML.""" d = qm.extension.get_class_description(self.item.GetClass()) return qm.web.format_structured_text(d) def GetBriefClassDescription(self): """Return a brief description of the test or resource class. returns -- The brief description, formatted as HTML.""" d = qm.extension.get_class_description(self.item.GetClass(), brief=1) return qm.web.format_structured_text(d) def MakeEditUrl(self): """Return the URL for editing this item.""" return qm.web.WebRequest("edit-" + self.type, base=self.request, id=self.item.GetId()).AsUrl() def MakeRunUrl(self): """Return the URL for running this item.""" return qm.web.WebRequest("run-tests", base=self.request, ids=self.item.GetId()).AsUrl() def MakeShowUrl(self): """Return the URL for showing this item.""" return qm.web.WebRequest("show-" + self.type, base=self.request, id=self.item.GetId()).AsUrl() def MakeSubmitUrl(self): """Return the URL for submitting edits.""" return qm.web.WebRequest("submit-" + self.type, base=self.request).AsUrl() def MakeDeleteScript(self): """Make a script to confirm deletion of the test or resource. returns -- JavaScript source to handle deletion of the test or resource.""" item_id = self.item.GetId() delete_url = qm.web.make_url("delete-" + self.type, base_request=self.request, id=item_id) message = """

Are you sure you want to delete the %s %s?

""" % (self.type, item_id) return self.server.MakeConfirmationDialog(message, delete_url) class ShowSuitePage(QMTestPage): """Page for displaying the contents of a test suite.""" def __init__(self, server, suite, edit, is_new_suite): """Construct a new DTML context. 'server' -- The 'QMTestServer' creating this page. 'suite' -- The 'Suite' instance to display. 'edit' -- If true, display controls for editing the suite. 'is_new_suite' -- If true, the suite being displayed is being created at this time.""" # Initialize the base class. QMTestPage.__init__(self, "suite.dtml", server) # It does not make sense to display a new suite without being # able to edit it; there is nothing to show. assert edit or not is_new_suite # Set up attributes. database = server.GetDatabase() self.suite = suite self.test_ids = suite.GetTestIds() self.suite_ids = suite.GetSuiteIds() self.edit = edit self.is_new_suite = is_new_suite if not suite.IsImplicit() and database.IsModifiable(): self.edit_menu_items.append(("Edit Suite", "javascript:edit_suite();")) self.edit_menu_items.append(("Delete Suite", "javascript:delete_suite();")) if not edit: self.run_menu_items.append(("This Suite", "javascript:run_suite();")) if edit: # Find the directory path containing this suite. (dirname, basename) = self.GetDatabase().SplitLabel(suite.GetId()) # Construct a list of all test IDs, relative to the suite, # that are not explicitly included in the suite. excluded_test_ids = database.GetTestIds(dirname) for test_id in self.test_ids: if test_id in excluded_test_ids: excluded_test_ids.remove(test_id) # Make controls for adding or removing test IDs. self.test_id_controls = qm.web.make_choose_control( "test_ids", "Included Tests", self.test_ids, "Available Tests", excluded_test_ids) # Likewise for suite IDs. excluded_suite_ids = database.GetSuiteIds(dirname) for suite_id in self.suite_ids: if suite_id in excluded_suite_ids: excluded_suite_ids.remove(suite_id) # Don't show the suite as a candidate for inclusion in # itself. self_suite_id = basename if self_suite_id in excluded_suite_ids: excluded_suite_ids.remove(self_suite_id) # Make controls for adding or removing suite IDs. self.suite_id_controls = qm.web.make_choose_control( "suite_ids", "Included Suites", self.suite_ids, "Available Suites", excluded_suite_ids) def MakeEditUrl(self): """Return the URL for editing this suite.""" return qm.web.WebRequest("edit-suite", base=self.request, id=self.suite.GetId()) \ .AsUrl() def MakeRunUrl(self): """Return the URL for running this suite.""" return qm.web.WebRequest("run-tests", base=self.request, ids=self.suite.GetId()) \ .AsUrl() def MakeDeleteScript(self): """Make a script to confirm deletion of the suite. returns -- JavaScript source for a function, 'delete_script', which shows a popup confirmation window.""" suite_id = self.suite.GetId() delete_url = qm.web.make_url("delete-suite", base_request=self.request, id=suite_id) message = """

Are you sure you want to delete the suite %s?

""" % suite_id return self.server.MakeConfirmationDialog(message, delete_url) class StorageResultsStream(ResultStream): """A 'StorageResultsStream' stores results. A 'StorageResultsStream' does not write any output. It simply stores the results for future display.""" def __init__(self): """Construct a 'StorageResultsStream'.""" super(StorageResultsStream, self).__init__({}) self.__test_results = {} self.__test_results_in_order = [] self.__resource_results = {} # The stream is not finished yet. self.__is_finished = 0 # And there are no annotations yet. self.__annotations = {} # Create a lock for synchronization between the test execution # thread (which will call methods like 'WriteResults' and # 'Summarize') and the GUI thread (which will call # 'GetTestResults' and 'IsFinished'). self.__lock = Lock() def GetAnnotations(self): """Return the annotations for this run.""" return self.__annotations def WriteAnnotation(self, key, value): self.__annotations[key] = value def WriteResult(self, result): """Output a test result. 'result' -- A 'Result'.""" self.__lock.acquire() try: if result.GetKind() == Result.TEST: self.__test_results[result.GetId()] = result self.__test_results_in_order.append(result) else: self.__resource_results[result.GetId()] = result finally: self.__lock.release() def Summarize(self): """Output summary information about the results. When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point. Derived class methods may override this method. They should, however, invoke this version before returning.""" # Mark the stream as finished. self.__lock.acquire() ResultStream.Summarize(self) self.__is_finished = 1 self.__lock.release() def Start(self, test_ids): """Start collecting results. 'test_ids' -- The names of the tests that we are about to run. Start collecting new results. Discard results for the 'test_ids', but not for other tests.""" self.__lock.acquire() self.__is_finished = 0 # Go through all of the tests we are about to run and remove # corresponding results. for id in test_ids: if self.__test_results.has_key(id): del self.__test_results[id] self.__test_results_in_order \ = filter(lambda r, rs=self.__test_results: \ rs.has_key(r.GetId()), self.__test_results_in_order) self.__lock.release() def IsFinished(self): """Return true iff no more results are forthcoming. returns -- True if no more results will be written to this stream.""" self.__lock.acquire() finished = self.__is_finished self.__lock.release() return finished def GetTestResults(self): """Return the accumulated test results. returns -- A dictionary mapping test names to 'Result' objects.""" self.__lock.acquire() results = self.__test_results self.__lock.release() return results def GetTestResultsInOrder(self): """Return the test results in the order they appeared. returns -- A sequence of test results, in the order that they appeared.""" self.__lock.acquire() results = self.__test_results_in_order self.__lock.release() return results def GetResourceResults(self): """Return the accumulated resource results. returns -- A dictionary mapping resource names to 'Result' objects.""" self.__lock.acquire() results = self.__resource_results self.__lock.release() return results def GetResult(self, name): """Return the 'Result' with the indicated 'name'. 'name' -- A string giving the name of a test or resource result. returns -- The 'Result' instance corresponding to 'name'.""" self.__lock.acquire() result = self.__test_results.get(name) if not result: result = self.__resource_results.get(name) self.__lock.release() return result class TestResultsPage(QMTestPage): """DTML page for displaying test results.""" def __init__(self, server): """Construct a new 'TestResultsPage'. 'server' -- The 'QMTestServer' creating this page.""" # Initialize the base classes. QMTestPage.__init__(self, "results.dtml", server) results_stream = server.GetResultsStream() # It is important that we ask for IsFinished before asking # for GetTestResults. The stream could be finished between # the two calls, and it is better to show all the results but # claim they are incomplete than to show only some of the # results and claim they are complete. self.__is_finished = results_stream.IsFinished() self.test_results = results_stream.GetTestResultsInOrder() self.expected_outcomes = server.GetExpectedOutcomes() def GetOutcomes(self): """Return the list of result outcomes. returns -- A sequence of result outcomes.""" return Result.outcomes def GetTotal(self): """Return the total number of tests. returns -- The total number of tests.""" return len(self.test_results) def GetTotalUnexpected(self): """Return the total number of unexpected results. returns -- The total number of unexpected results.""" return len(self.GetRelativeResults(self.test_results, 0)) def GetResultsWithOutcome(self, outcome): """Return the number of tests with the given 'outcome'. 'outcome' -- One of the 'Result.outcomes'. returns -- The results with the given 'outcome'.""" return filter(lambda r, o=outcome: r.GetOutcome() == o, self.test_results) def GetCount(self, outcome): """Return the number of tests with the given 'outcome'. 'outcome' -- One of the 'Result.outcomes'. returns -- The number of tests with the given 'outcome'.""" return len(self.GetResultsWithOutcome(outcome)) def GetUnexpectedCount(self, outcome): """Return the number of tests with the given 'outcome'. 'outcome' -- One of the 'Result.outcomes'. returns -- The number of tests with the given 'outcome' that were expected to have some other outcome.""" results = self.GetResultsWithOutcome(outcome) results = self.GetRelativeResults(results, 0) return len(results) def GetRelativeResults(self, results, expected): """Return the results that match, or fail to match, expectations. 'results' -- A sequence of 'Result' objects. 'expected' -- A boolean. If true, expected results are returned. If false, unexpected results are returned.""" if expected: return filter(lambda r, er=self.expected_outcomes: \ r.GetOutcome() == er.get(r.GetId(), Result.PASS), results) else: return filter(lambda r, er=self.expected_outcomes: \ r.GetOutcome() != er.get(r.GetId(), Result.PASS), results) def GetDetailUrl(self, test_id): """Return the detail URL for a test. 'test_id' -- The name of the test. returns -- The URL that contains details about the 'test_id'.""" return qm.web.WebRequest("show-result", base=self.request, id=test_id).AsUrl() def IsFinished(self): """Return true iff no more results are forthcoming. returns -- True if no more tests are running.""" return self.__is_finished def GetRefreshDelay(self): """Returns the number of seconds to wait before refreshing the page. returns -- The number of seconds to wait before refreshing this page. A value of zero means that te page should never be refreshed. This function is only called if 'IsFinished' returns true.""" return 10 class QMTestServer(qm.web.WebServer): """A 'QMTestServer' is the web GUI interface to QMTest.""" def __init__(self, database, port, address, log_file, targets, context, expectations, run_db): """Create and bind an HTTP server. 'database' -- The test database to serve. 'port' -- The port number on which to accept HTTP requests. 'address' -- The local address to which to bind the server. An empty string indicates all local addresses. 'log_file' -- A file object to which the server will log requests. 'None' for no logging. 'targets' -- A sequence of 'Target' objects to use when running tests. 'context' -- The 'Context' in which tests will execute.""" qm.web.WebServer.__init__(self, port, address, log_file=log_file) self.__database = database self.__targets = targets self.__context = context # Register all our web pages. for name, function in [ ( "/test/clear-results", self.HandleClearResults ), ( "/test/create-resource", self.HandleShowItem ), ( "/test/create-suite", self.HandleCreateSuite ), ( "/test/create-test", self.HandleShowItem ), ( "/test/delete-resource", self.HandleDeleteItem ), ( "/test/delete-suite", self.HandleDeleteSuite ), ( "/test/delete-test", self.HandleDeleteItem ), ( "/test/dir", self.HandleDir ), ( "/test/edit-context", self.HandleEditContext ), ( "/test/edit-resource", self.HandleShowItem ), ( "/test/edit-suite", self.HandleEditSuite ), ( "/test/edit-test", self.HandleShowItem ), ( "/test/load-context", self.HandleLoadContext ), ( "/test/load-expectations", self.HandleLoadExpectations ), ( "/test/load-results", self.HandleLoadResults ), ( "/test/new-resource", self.HandleNewResource ), ( "/test/new-suite", self.HandleNewSuite ), ( "/test/new-test", self.HandleNewTest ), ( "/test/run-tests", self.HandleRunTests ), ( "/test/set-expectation", self.HandleSetExpectation ), ( "/test/show-dir", self.HandleDir ), ( "/test/show-resource", self.HandleShowItem ), ( "/test/show-result", self.HandleShowResult ), ( "/test/show-results", self.HandleShowResults ), ( "/test/show-suite", self.HandleShowSuite ), ( "/test/show-test", self.HandleShowItem ), ( "/test/shutdown", self.HandleShutdown ), ( "/test/stop-tests", self.HandleStopTests ), ( "/test/submit-context", self.HandleSubmitContext ), ( "/test/submit-context-file", self.HandleSubmitContextFile ), ( "/test/submit-expectation", self.HandleSubmitExpectation ), ( "/test/submit-resource", self.HandleSubmitItem ), ( "/test/submit-expectations", self.HandleSubmitExpectations ), ( "/test/submit-expectations-form", self.HandleSubmitExpectationsForm ), ( "/test/submit-results", self.HandleSubmitResults ), ( "/test/submit-suite", self.HandleSubmitSuite ), ( "/test/submit-test", self.HandleSubmitItem ), ( "/test/" + qm.test.cmdline.QMTest.context_file_name, self.HandleSaveContext ), ( "/test/" + qm.test.cmdline.QMTest.expectations_file_name, self.HandleSaveExpectations ), ( "/test/" + qm.test.cmdline.QMTest.results_file_name, self.HandleSaveResults ), ( "/report/dir", self.HandleDirReport ), ( "/report/show-dir", self.HandleDirReport ), ( "/report/show-test", self.HandleShowItemReport ), ( "/report/show-resource", self.HandleShowItemReport ), ( "/report/show-result", self.HandleShowResultReport ), ( "/report/show-result", self.HandleShowResult ), ]: self.RegisterScript(name, function) self.RegisterPathTranslation( "/stylesheets", qm.get_share_directory("web", "stylesheets")) self.RegisterPathTranslation( "/images", qm.get_share_directory("web", "images")) self.RegisterPathTranslation( "/static", qm.get_share_directory("web", "static")) # Register the QM manual. self.RegisterPathTranslation( "/tutorial", qm.get_doc_directory("html", "tutorial")) # The DB's attachment store processes download requests for # attachment data. attachment_store = database.GetAttachmentStore() if attachment_store: self.RegisterScript(qm.fields.AttachmentField.download_url, attachment_store.HandleDownloadRequest) self.__expectation_db = expectations self.__expected_outcomes = {} for test_id in self.__database.GetTestIds(): result = expectations.Lookup(test_id) self.__expected_outcomes[test_id] = result.GetOutcome() self.__run_db = run_db # There are no results yet. self.__results_stream = StorageResultsStream() self.__results_stream.Summarize() # There is no execution thread. self.__execution_thread = None # Bind the server to the specified address. try: self.Bind() except qm.web.AddressInUseError, address: raise RuntimeError, qm.error("address in use", address=address) except qm.web.PrivilegedPortError: raise RuntimeError, qm.error("privileged port", port=port) def GetContext(self): """Return the 'Context' in which tests will be run. returns -- The 'Context' in which tests will be run.""" return self.__context def GetDatabase(self): """Return the 'Database' handled by this server. returns -- The 'Database' handled by this server.""" return self.__database def GetRunDatabase(self): """Return the 'RunDatabase' handled by this server. returns -- The 'RunDatabase' handled by this server.""" return self.__run_db def GetExpectationDatabase(self): """Return the current ExpectationDatabase. returns -- The ExpectationDatabase instance.""" return self.__expectation_db def GetExpectedOutcomes(self): """Return the current expected outcomes for the test database. returns -- A map from test IDs to outcomes. Some tests may have not have an entry in the map.""" return self.__expected_outcomes def GetHTMLClassForOutcome(self, outcome): """Return the CSS class for the 'outcome'. 'outcome' -- One of the result outcomes. returns -- The name of a CSS class. These are used with elements. See 'qm.css'.""" return { Result.PASS: "qmtest_pass", Result.FAIL: "qmtest_fail", Result.UNTESTED: "qmtest_untested", Result.ERROR: "qmtest_error", "EXPECTED" : "qmtest_expected" }[outcome] def GetResultsStream(self): """Return the 'StorageResultsStream' containing test results. returns -- The 'StorageResultsStream' associated with this server.""" return self.__results_stream def HandleClearResults(self, request): """Handle a request to clear the current test results. 'request' -- A 'WebRequest' object.""" # Eliminate the old results stream. del self.__results_stream # And create a new one. self.__results_stream = StorageResultsStream() self.__results_stream.Summarize() # Redirect to the main page. request = qm.web.WebRequest("dir", base=request) raise qm.web.HttpRedirect, request def HandleCreateSuite(self, request): """Handle a submission of a new test suite. 'request' -- A 'WebRequest' object.""" field_errors = {} database = self.__database # Extract the suite ID of the new suite from the request. suite_id = request["id"] # Check that the ID is valid. if not database.IsValidLabel(suite_id, is_component = 0): field_errors["_id"] = qm.error("invalid id", id=suite_id) # Check that the ID doesn't already exist. elif database.HasSuite(suite_id): field_errors["_id"] = qm.error("suite already exists", suite_id=suite_id) # Were there any validation errors? if len(field_errors) > 0: # Yes. Instead of showing the page for editing the suite, # redisplay the new suite page with error messages. return NewSuitePage(self, suite_id, field_errors)(request) else: # Everything looks good. Make an empty suite. suite_class = qm.test.base.get_extension_class( "explicit_suite.ExplicitSuite", "suite", self.GetDatabase()) extras = { suite_class.EXTRA_DATABASE : self.GetDatabase(), suite_class.EXTRA_ID : suite_id } suite = suite_class({}, **extras) # Show the editing page. return ShowSuitePage(self, suite, edit=1, is_new_suite=1)(request) def HandleDeleteItem(self, request): """Handle a request to delete a test or resource. This function handles the script requests 'delete-test' and 'delete-resource'. 'request' -- A 'WebRequest' object. The ID of the test or resource to delete is specified in the 'id' field of the request.""" database = self.__database # Extract the item ID. item_id = request["id"] # The script name determines whether we're deleting a test or an # resource. script_name = request.GetScriptName() if script_name == "delete-test": database.RemoveExtension(item_id, database.TEST) elif script_name == "delete-resource": database.RemoveExtension(item_id, database.RESOURCE) else: raise RuntimeError, "unrecognized script name" # Redirect to the main page. request = qm.web.WebRequest("dir", base=request) raise qm.web.HttpRedirect, request def HandleDeleteSuite(self, request): """Handle a request to delete a test suite. 'request' -- A 'WebRequest' object. The ID of the suite to delete is specified in the 'id' field of the request.""" database = self.__database # Extract the suite ID. suite_id = request["id"] database.RemoveExtension(suite_id, database.SUITE) # Redirect to the main page. raise qm.web.HttpRedirect, qm.web.WebRequest("dir", base=request) def HandleDir(self, request): """Generate a directory page. 'request' -- A 'WebRequest' object. The request has these fields: 'path' -- A path in test/resource/suite ID space. If specified, only tests and resources in this subtree are displayed, and their IDs are displayed relative to this path. If omitted, the entire contents of the test database are shown.""" path = request.get("id", "") return DirPage(self, path)(request) def HandleDirReport(self, request): """Generate a directory report page. 'request' -- A 'WebRequest' object. The request has these fields: 'path' -- A path in test/resource/suite ID space. If specified, only tests and resources in this subtree are displayed, and their IDs are displayed relative to this path. If omitted, the entire contents of the test database are shown.""" path = request.get("id", "") return DirReportPage(self, path)(request) def HandleEditContext(self, request): """Handle a request to edit the context. 'request' -- The 'WebRequest' that caused the event.""" context_page = ContextPage(self) return context_page(request) def HandleEditSuite(self, request): """Generate the page for editing a test suite.""" return self.HandleShowSuite(request, edit=1) def HandleLoadContext(self, request): """Handle a request to upload a context file. 'request' -- The 'WebRequest' that caused the event.""" return LoadContextPage(self)(request) def HandleLoadExpectations(self, request): """Handle a request to upload results. 'request' -- The 'WebRequest' that caused the event.""" return LoadExpectationsPage(self)(request) def HandleLoadResults(self, request): """Handle a request to upload results. 'request' -- The 'WebRequest' that caused the event.""" return LoadResultsPage(self)(request) def HandleNewResource(self, request): """Handle a request to create a new test. 'request' -- The 'WebRequest' that caused the event.""" return NewItemPage(self, "resource")(request) def HandleNewTest(self, request): """Handle a request to create a new test. 'request' -- The 'WebRequest' that caused the event.""" return NewItemPage(self, "test")(request) def HandleNewSuite(self, request): """Handle a request to create a new suite. 'request' -- The 'WebRequest' that caused the event.""" return NewSuitePage(self)(request) def HandleRunTests(self, request): """Handle a request to run tests. 'request' -- The 'WebRequest' that caused the event. These fields in 'request' are used: 'ids' -- A comma-separated list of test and suite IDs. These IDs are expanded into the list of IDs of tests to run. """ # Extract and expand the IDs of tests to run. if request.has_key("ids"): ids = string.split(request["ids"], ",") # '.' is an alias for , and thus shadows other selectors. if '.' in ids: ids = [""] else: ids = [""] test_ids = self.GetDatabase().ExpandIds(ids)[0] # Let the results stream know that we are going to start # providing it with results. self.__results_stream.Start(test_ids) # Create the thread that will run all of the tests. del self.__execution_thread test_ids.sort() self.__execution_thread = \ ExecutionThread(self.__database, test_ids, self.__context, self.__targets, [self.__results_stream], self.__expectation_db) # Start the thread. self.__execution_thread.start() # Sleep for a few seconds so that if we're only running one # test there's a good chance that it will finish before we # show the results page. time.sleep(5) # Redirect to the results page. request = qm.web.WebRequest("show-results", base=request) raise qm.web.HttpRedirect, request def HandleSaveContext(self, request): """Handlea request to save the context to a file. 'request' -- The 'WebRequest' that caused the event.""" # Start with the empty string. s = "" # Run through all of the context variables. for (name, value) in self.__context.items(): s = s + "%s=%s\n" % (name, value) return ("application/x-qmtest-context", s) def HandleSaveExpectations(self, request): """Handle a request to save expectations to a file. 'request' -- The 'WebRequest' that caused the event.""" # Create a string stream to store the results. s = StringIO.StringIO() # Create a results stream for storing the results. rsc = qm.test.cmdline.get_qmtest().GetFileResultStreamClass() rs = rsc({ "file" : s }) # Write all the results. for (id, outcome) in self.__expected_outcomes.items(): r = Result(Result.TEST, id, outcome) rs.WriteResult(r) # Terminate the stream. rs.Summarize() # Extract the data. data = s.getvalue() # Close the stream. s.close() return ("application/x-qmtest-results", data) def HandleSaveResults(self, request): """Handle a request to save results to a file. 'request' -- The 'WebRequest' that caused the event.""" # Create a string stream to store the results. s = StringIO.StringIO() # Create a results stream for storing the results. rsc = qm.test.cmdline.get_qmtest().GetFileResultStreamClass() rs = rsc({ "file" : s }) # Write all the annotations. rs.WriteAllAnnotations(self.__results_stream.GetAnnotations()) # Write all the results. for r in self.__results_stream.GetTestResults().values(): rs.WriteResult(r) for r in self.__results_stream.GetResourceResults().values(): rs.WriteResult(r) # Terminate the stream. rs.Summarize() # Extract the data. data = s.getvalue() # Close the stream. s.close() return ("application/x-qmtest-results", data) def HandleSetExpectation(self, request): """Handle a request to set expectations. 'request' -- A 'WebRequest' object.""" return SetExpectationPage(self, request["id"])(request) def HandleShowItem(self, request): """Handle a request to show a test or resource. 'request' -- A 'WebRequest' object. This function generates pages to handle these requests: 'create-test' -- Generate a form for initial editing of a test about to be created, given its test ID and test class. 'create-resource' -- Likewise for an resource. 'show-test' -- Display a test. 'show-resource' -- Likewise for an resource. 'edit-test' -- Generate a form for editing an existing test. 'edit-resource' -- Likewise for an resource. This function distinguishes among these cases by checking the script name of the request object. The request must have the following fields: 'id' -- A test or resource ID. For show or edit pages, the ID of an existing item. For create pages, the ID of the item being created. 'class' -- For create pages, the name of the test or resource class. """ # Paramaterize this function based on the request's script name. url = request.GetScriptName() edit, create, type = { "show-test": (0, 0, "test"), "edit-test": (1, 0, "test"), "create-test": (1, 1, "test"), "show-resource": (0, 0, "resource"), "edit-resource": (1, 0, "resource"), "create-resource": (1, 1, "resource"), }[url] database = self.__database try: # Determine the ID of the item. item_id = request["id"] except KeyError: # The user probably submitted the form without entering an ID. message = qm.error("no id for show") return qm.web.generate_error_page(request, message) if create: # We're in the middle of creating a new item. class_name = request["class"] # First perform some validation. field_errors = {} # Check that the ID is valid. if not database.IsValidLabel(item_id, is_component = 0): field_errors["_id"] = qm.error("invalid id", id=item_id) else: # Check that the ID doesn't already exist. if type == "resource": if database.HasResource(item_id): field_errors["_id"] \ = qm.error("resource already exists", resource_id=item_id) elif type == "test": if database.HasTest(item_id): field_errors["_id"] = qm.error("test already exists", test_id=item_id) # Check that the class exists. try: qm.test.base.get_extension_class(class_name, type, database) except ValueError: # The class name was incorrectly specified. field_errors["_class"] = qm.error("invalid class name", class_name=class_name) except: # Can't find the class. field_errors["_class"] = qm.error("class not found", class_name=class_name) # Were there any errors? if len(field_errors) > 0: # Yes. Instead of showing the edit page, re-show the new # item page. page = NewItemPage(server=self, type=type, item_id=item_id, class_name=class_name, field_errors=field_errors) return page(request) # Construct a test with default argument values, as the # starting point for editing. if type == "resource": item = self.MakeNewResource(class_name, item_id) elif type == "test": item = self.MakeNewTest(class_name, item_id) else: # We're showing or editing an existing item. # Look it up in the database. if type == "resource": try: item = database.GetResource(item_id) except qm.test.database.NoSuchTestError, e: # An test with the specified test ID was not fount. # Show a page indicating the error. return qm.web.generate_error_page(request, str(e)) elif type == "test": try: item = database.GetTest(item_id) except qm.test.database.NoSuchResourceError, e: # An test with the specified resource ID was not fount. # Show a page indicating the error. return qm.web.generate_error_page(request, str(e)) # Generate HTML. return ShowItemPage(self, item, edit, create, type)(request) def HandleShowResult(self, request): """Handle a request to show result detail. If a 'test_run' argument was provided, fetch the result from the corresponding test run. Else read it from the results stream. 'request' -- The 'WebRequest' that caused the event.""" name = request["id"] test_run = request.get("test_run") if test_run: run_db = self.GetRunDatabase() result = run_db.GetAllRuns()[int(test_run)].GetResult(name) else: result = self.__results_stream.GetResult(name) return ResultPage(self, result)(request) def HandleShowResults(self, request): """Handle a request to show results. 'request' -- The 'WebRequest' that caused the event.""" # Display the results. results_page = TestResultsPage(self) return results_page(request) def HandleShowItemReport(self, request): """Handle a request to show a test or resource report. 'request' -- A 'WebRequest' object. This function generates pages to handle these requests: 'show-test' -- Display a test. 'show-resource' -- Likewise for an resource. This function distinguishes among these cases by checking the script name of the request object. The request must have the following fields: 'id' -- A test or resource ID. For show or edit pages, the ID of an existing item. For create pages, the ID of the item being created.""" # Paramaterize this function based on the request's script name. url = request.GetScriptName() type = {"show-test": "test", "show-resource": "resource"}[url] database = self.GetDatabase() try: # Determine the ID of the item. item_id = request["id"] except KeyError: # The user probably submitted the form without entering an ID. message = qm.error("no id for show") return qm.web.generate_error_page(request, message) if type == "resource": try: item = database.GetResource(item_id) except qm.test.database.NoSuchTestError, e: return qm.web.generate_error_page(request, str(e)) elif type == "test": try: item = database.GetTest(item_id) except qm.test.database.NoSuchResourceError, e: return qm.web.generate_error_page(request, str(e)) # Generate HTML. return ShowItemReportPage(self, item, type)(request) def HandleShowResultReport(self, request): """Handle a request to show result report. 'request' -- The 'WebRequest' that caused the event.""" return xxx #name = request["id"] #result = self.__results_stream.GetResult(name) #return ResultPage(self, result)(request) def HandleShowSuite(self, request, edit=0): """Generate the page for displaying or editing a test suite. 'request' -- A 'WebRequest' object. 'edit' -- If true, display the page for editing the suite. Otherwise, just display the suite. The request has the following fields: 'id' -- The ID of the suite to display or edit.""" database = self.__database try: # Determine the suite ID. suite_id = request["id"] except KeyError: # No suite ID was given. message = qm.error("no id for show") return qm.web.generate_error_page(request, message) else: suite = database.GetSuite(suite_id) # Generate HTML. return ShowSuitePage(self, suite, edit, is_new_suite=0)(request) def HandleShutdown(self, request): """Handle a request to shut down the server. 'request' -- The 'WebRequest' that caused the event.""" raise SystemExit, None def HandleStopTests(self, request): """Handle a request to stop test execution. 'request' -- The 'WebRequest' that caused the event.""" # Stop the thread. self.__execution_thread.RequestTermination() # Redirect to the results page. request = qm.web.WebRequest("show-results", base=request) raise qm.web.HttpRedirect, request def HandleSubmitContext(self, request): """Handle a context submission.. 'request' -- The 'WebRequest' that caused the event. The 'request' must have a 'context_vars' key, whose value is the the context variables.""" vars = qm.web.decode_properties(request["context_vars"]) self.__context = Context() for k in vars.keys(): self.__context[k] = vars[k] # Redirect to the main page. request = qm.web.WebRequest("dir", base=request) raise qm.web.HttpRedirect, request def HandleSubmitContextFile(self, request): """Handle a context file submission.. 'request' -- The 'WebRequest' that caused the event.""" # The context data. data = request["file"] # Create a file objet to read from. file = StringIO.StringIO(data) # Parse the assignments in the context file. assignments = qm.common.read_assignments(file) # Add them to the context. for (name, value) in assignments.items(): try: self.__context[name] = value except ValueError: # Skip any invalid assignments. pass # Redirect to the main page. return self._ClosePopupAndRedirect("dir") def HandleSubmitExpectation(self, request): """Handle setting a single expectation. 'request' -- The 'WebRequest' that caused the event.""" id = request["id"] outcome = request["outcome"] self.__expected_outcomes[id] = outcome # Close the upload popup window, and reload the main window. return self._ClosePopupAndRedirect(request["url"]) def HandleSubmitExpectations(self, request): """Handle uploading expected results. 'request' -- The 'WebRequest' that caused the event.""" # Get the results file data. data = request["file"] # Create a file object from the data. f = StringIO.StringIO(data) # Read the results. self.__expectation_db = \ qm.test.base.load_expectations(f, self.GetDatabase()) self.__expected_outcomes = {} for test_id in self.GetDatabase().GetTestIds(): expectation = self.__expectation_db.Lookup(test_id) self.__expected_outcomes[test_id] = expectation.GetOutcome() # Close the upload popup window, and redirect the main window # to the root of the database. return self._ClosePopupAndRedirect("dir") def HandleSubmitExpectationsForm(self, request): """Handle uploading expected results. 'request' -- The 'WebRequest' that caused the event.""" # Clear out the current set of expected outcomes; the entire # set of new self.__expected_outcomes = {} # Loop over all the tests. for id in self.GetDatabase().ExpandIds("")[0]: outcome = request[id] if outcome != "None": self.__expected_outcomes[id] = outcome # Redirect to the main page. request = qm.web.WebRequest("dir", base=request) raise qm.web.HttpRedirect, request def HandleSubmitItem(self, request): """Handle a test or resource submission. This function handles submission of the test or resource editing form generated by 'handle_show'. The script name in 'request' should be 'submit-test' or 'submit-resource'. It constructs the appropriate 'Test' or 'Resource' object and writes it to the database, either as a new item or overwriting an existing item. The request must have the following form fields: 'id' -- The test or resource ID of the item being edited or created. 'class' -- The name of the test or resource class of this item. arguments -- Argument values are encoded in fields whose names start with 'qm.fields.Field.form_field_prefix'.""" if request.GetScriptName() == "submit-test": type = "test" elif request.GetScriptName() == "submit-resource": type = "resource" # Make sure there's an ID in the request, and extract it. try: item_id = request["id"] except KeyError: message = qm.error("no id for submit") return qm.web.generate_error_page(request, message) database = self.__database # Learn whether or not this is a new item. is_new = int(request["is_new"]) # Extract the class and field specification. item_class_name = request["class"] item_class = qm.test.base.get_extension_class(item_class_name, type, database) fields = get_class_arguments(item_class) # We'll perform various kinds of validation as we extract form # fields. Errors are placed into this map. field_errors = {} redisplay = 0 # Loop over fields of the class, looking for arguments in the # submitted request. arguments = {} temporary_store = self.GetTemporaryAttachmentStore() main_store = database.GetAttachmentStore() attachment_stores = { id(temporary_store): temporary_store, id(main_store): main_store } for field in fields: # Construct the name we expect for the corresponding argument. field_name = field.GetName() form_field_name = field.GetHtmlFormFieldName() # Parse the value for this field. try: value, r = field.ParseFormValue(request, form_field_name, attachment_stores) if r: redisplay = 1 arguments[field_name] = value except: # Something went wrong parsing the value. Associate an # error message with this field. message = str(sys.exc_info()[1]) field_errors[field_name] = message redisplay = 1 if type == "test": # Create a new test. item = TestDescriptor( database, test_id=item_id, test_class_name=item_class_name, arguments=arguments) elif type == "resource": # Create a new resource. item = ResourceDescriptor(database, item_id, item_class_name, arguments) # If necessary, redisplay the form. if redisplay: request = qm.web.WebRequest("edit-" + type, base=request, id=item_id) return ShowItemPage(self, item, 1, is_new, type, field_errors)(request) # Store it in the database. database.WriteExtension(item_id, item.GetItem()) # Redirect to a page that displays the newly-edited item. request = qm.web.WebRequest("show-" + type, base=request, id=item_id) raise qm.web.HttpRedirect, request def HandleSubmitResults(self, request): """Handle uploading results. 'request' -- The 'WebRequest' that caused the event.""" # Get the results file data. data = request["file"] # Create a file object from the data. f = StringIO.StringIO(data) # Read the results. results = qm.test.base.load_results(f, self.GetDatabase()) # Enter them into a new results stream. self.__results_stream = StorageResultsStream() annotations = results.GetAnnotations() self.__results_stream.WriteAllAnnotations(annotations) for r in results: self.__results_stream.WriteResult(r) self.__results_stream.Summarize() # Close the upload popup window, and redirect the main window # to a view of the results. return self._ClosePopupAndRedirect("show-results") def HandleSubmitSuite(self, request): """Handle test suite submission. 'request' -- A 'WebRequest' object. The request object has these fields: 'id' -- The ID of the test suite being edited. If a suite with this ID exists, it is replaced (it must not be an implicit suite though). Otherwise a new suite is edited. 'test_ids' -- A comma-separated list of test IDs to include in the suite, relative to the suite's own ID. 'suite_ids' -- A comma-separated list of other test suite IDs to include in the suite, relative to the suite's own ID. """ database = self.__database # Extract fields from the request. suite_id = request["id"] test_ids = request["test_ids"] if string.strip(test_ids) == "": test_ids = [] else: test_ids = string.split(test_ids, ",") suite_ids = request["suite_ids"] if string.strip(suite_ids) == "": suite_ids = [] else: suite_ids = string.split(suite_ids, ",") # Construct a new suite. suite_class = qm.test.base.get_extension_class( "explicit_suite.ExplicitSuite", "suite", self.GetDatabase()) extras = { suite_class.EXTRA_DATABASE : self.GetDatabase(), suite_class.EXTRA_ID : suite_id } suite = suite_class({ "test_ids" : test_ids, "suite_ids" : suite_ids }, **extras) # Store it. database.WriteExtension(suite_id, suite) # Redirect to a page that displays the newly-edited item. raise qm.web.HttpRedirect, \ qm.web.WebRequest("show-suite", base=request, id=suite_id) def MakeNewTest(self, test_class_name, test_id): """Create a new test with default arguments. 'test_class_name' -- The name of the test class of which to create a new test. 'test_id' -- The test ID of the new test. returns -- A new 'TestDescriptor' object.""" test_class = qm.test.base.get_test_class(test_class_name, self.GetDatabase()) # Make sure there isn't already such a test. if self.GetDatabase().HasTest(test_id): raise RuntimeError, qm.error("test already exists", test_id=test_id) # Construct an argument map containing default values. arguments = {} for field in get_class_arguments(test_class): name = field.GetName() value = field.GetDefaultValue() arguments[name] = value # Construct a default test instance. return TestDescriptor(self.GetDatabase(), test_id, test_class_name, arguments) def MakeNewResource(self, resource_class_name, resource_id): """Create a new resource with default arguments. 'resource_class_name' -- The name of the resource class of which to create a new resource. 'resource_id' -- The resource ID of the new resource. returns -- A new 'ResourceDescriptor' object.""" resource_class \ = qm.test.base.get_resource_class(resource_class_name, self.GetDatabase()) # Make sure there isn't already such a resource. if self.GetDatabase().HasResource(resource_id): raise RuntimeError, qm.error("resource already exists", resource_id=resource_id) # Construct an argument map containing default values. arguments = {} for field in get_class_arguments(resource_class): name = field.GetName() value = field.GetDefaultValue() arguments[name] = value # Construct a default resource instance. return ResourceDescriptor(self.GetDatabase(), resource_id, resource_class_name, arguments) def _HandleRoot(self, request): """Handle the '/' URL.""" raise qm.web.HttpRedirect, qm.web.WebRequest("/test/dir") def _ClosePopupAndRedirect(self, url): """Close the current window. Redirect the main window to 'url'. 'url' -- A string giving the URL to which the main window should be redirected. returns -- A string giving HTML that will close the current window and redirect the main window to 'url'.""" return """""" % url ######################################################################## # initialization ######################################################################## # Use our 'DefaultDtmlPage' subclass even when generating generic # (non-QMTest) pages. #qm.web.DtmlPage.default_class = DefaultDtmlPage ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/web/__init__.py0000664000076400007640000000103511107032225016641 0ustar stefanstefan######################################################################## # # File: __init__.py # Author: Alex Samuel # Date: 2001-04-09 # # Contents: # Initialization for module qm.test.web. # # Copyright (c) 2001 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/reader_test_run.py0000664000076400007640000000411211107032225017511 0ustar stefanstefan######################################################################## # # File: reader_test_run.py # Author: Mark Mitchell # Date: 2005-08-08 # # Contents: # QMTest ReaderTestRun class. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.test.result import Result from qm.test.test_run import TestRun from qm.test.result_reader import ResultReader ######################################################################## # Classes ######################################################################## class ReaderTestRun(TestRun): """A 'ReaderTestRun' reads its results using a 'ResultReader'. A 'ResultReader' provides an iterative interface for reading results. A 'ReaderTestRun' uses a 'ResultReader' to populate a dictionary storing all the results from the reader.""" def __init__(self, reader): """Create a new 'ReaderTestRun' 'reader' -- The 'ResultReader' from which we are to read results.""" # Read the results. self.__results = {} for kind in Result.kinds: self.__results[kind] = {} for result in reader: self.__results[result.GetKind()][result.GetId()] = result # Read the annotations. self.__annotations = reader.GetAnnotations() def GetResult(self, id, kind = Result.TEST): return self.__results[kind].get(id) def GetAnnotation(self, key): return self.__annotations.get(key) def GetAnnotations(self): return self.__annotations def GetAllResults(self, directory = "", kind = Result.TEST): if directory == "": return self.__results[kind].values() else: return [self.__results[kind][id] for id in self.__results[kind] if id.startswith(directory)] qmtest-2.4.1/qm/test/resource_adapter.py0000664000076400007640000000234611107032225017662 0ustar stefanstefan######################################################################## # # File: resource_adapter.py # Author: Mark Mitchell # Date: 2005-09-02 # # Contents: # QMTest ResourceAdapter class. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.test.resource import Resource ######################################################################## # Classes ######################################################################## class ResourceAdapter(Resource): """A 'ResourceAdapter' converts test classes to resource classes. If 'C' is a test class, then a class derived from 'ResourceAdapter' and 'C' (in that order!) will be a resource class. The resource class 'Setup' method is equivalent to the 'Test' class 'Run' method. The 'CleanUp' action is empty.""" def SetUp(self, context, result): # To set up the resource, just run the underlying test class. self.Run(context, result) qmtest-2.4.1/qm/test/target.py0000664000076400007640000003666211107032225015631 0ustar stefanstefan######################################################################## # # File: target.py # Author: Mark Mitchell # Date: 10/29/2001 # # Contents: # QMTest Target class. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import qm import qm.common import qm.extension import qm.platform import qm.test.base from qm.test.context import * from qm.test.result import * from qm.test.database import NoSuchResourceError import re import signal import sys ######################################################################## # classes ######################################################################## class Target(qm.extension.Extension): """Base class for target implementations. A 'Target' is an entity that can run tests. QMTest can spread the workload from multiple tests across multiple targets. In addition, a single target can run more than one test at once. 'Target' is an abstract class. You can extend QMTest by providing your own target class implementation. To create your own target class, you must create a Python class derived (directly or indirectly) from 'Target'. The documentation for each method of 'Target' indicates whether you must override it in your target class implementation. Some methods may be overridden, but do not need to be. You might want to override such a method to provide a more efficient implementation, but QMTest will work fine if you just use the default version.""" arguments = [ qm.fields.TextField( name="name", title="Name", description="""The name of this target. The name of the target. The target name will be recorded in any tests executed on that target so that you can see where the test was run.""", default_value=""), qm.fields.TextField( name="group", title="Group", description="""The group associated with this target. Some tests may only be able to run on some targets. A test can specify a pattern indicating the set of targets on which it will run.""", default_value="") ] kind = "target" class __ResourceSetUpException(Exception): """An exception indicating that a resource could not be set up.""" def __init__(self, resource): """Construct a new 'ResourceSetUpException'. 'resource' -- The name of the resoure that could not be set up.""" self.resource = resource def __init__(self, database, arguments = None, **args): """Construct a 'Target'. 'database' -- The 'Database' containing the tests that will be run. 'arguments' -- As for 'Extension.__init__'. 'args' -- As for 'Extension.__init__'.""" if arguments: args.update(arguments) super(Target, self).__init__(**args) self.__database = database def GetName(self): """Return the name of the target. Derived classes must not override this method.""" return self.name def GetGroup(self): """Return the group of which the target is a member. Derived classes must not override this method.""" return self.group def GetDatabase(self): """Return the 'Database' containing the tests this target will run. returns -- The 'Database' containing the tests this target will run. Derived classes must not override this method.""" return self.__database def IsIdle(self): """Return true if the target is idle. returns -- True if the target is idle. If the target is idle, additional tasks may be assigned to it. Derived classes must override this method.""" raise NotImplementedError def IsInGroup(self, group_pattern): """Returns true if this 'Target' is in a particular group. 'group_pattern' -- A string giving a regular expression. returns -- Returns true if the 'group_pattern' denotes a regular expression that matches the group for this 'Target', false otherwise.""" return re.match(group_pattern, self.GetGroup()) def Start(self, response_queue, engine=None): """Start the target. 'response_queue' -- The 'Queue' in which the results of test executions are placed. 'engine' -- The 'ExecutionEngine' that is starting the target, or 'None' if this target is being started without an 'ExecutionEngine'. Derived classes may override this method, but the overriding method must call this method at some point during its execution.""" self.__response_queue = response_queue self.__engine = engine # There are no resources available on this target yet. self.__resources = {} self.__order_of_resources = [] def Stop(self): """Stop the target. Clean up all resources that have been set up on this target and take whatever other actions are required to stop the target. Derived classes may override this method.""" # Clean up any available resources. self.__order_of_resources.reverse() for name in self.__order_of_resources: rop = self.__resources[name] if rop and rop[1] == Result.PASS: self._CleanUpResource(name, rop[0]) del self.__response_queue del self.__engine del self.__resources del self.__order_of_resources def RunTest(self, descriptor, context): """Run the test given by 'test_id'. 'descriptor' -- The 'TestDescriptor' for the test. 'context' -- The 'Context' in which to run the test. Derived classes may override this method.""" # Create the result. result = Result(Result.TEST, descriptor.GetId()) try: # Augment the context appropriately. context = Context(context) context[context.TARGET_CONTEXT_PROPERTY] = self.GetName() context[context.TMPDIR_CONTEXT_PROPERTY] \ = self._GetTemporaryDirectory() context[context.DB_PATH_CONTEXT_PROPERTY] \ = descriptor.GetDatabase().GetPath() # Set up any required resources. self.__SetUpResources(descriptor, context) # Make the ID of the test available. context[context.ID_CONTEXT_PROPERTY] = descriptor.GetId() # Note the start time. result[Result.START_TIME] = qm.common.format_time_iso() # Run the test. try: descriptor.Run(context, result) finally: # Note the end time. result[Result.END_TIME] = qm.common.format_time_iso() except KeyboardInterrupt: result.NoteException(cause = "Interrupted by user.") # We received a KeyboardInterrupt, indicating that the # user would like to exit QMTest. Ask the execution # engine to stop. if self.__engine: self.__engine.RequestTermination() except qm.platform.SignalException, e: # Note the exception. result.NoteException(cause = str(e)) # If we get a SIGTERM, propagate it so that QMTest # terminates. if e.GetSignalNumber() == signal.SIGTERM: # Record the result so that the traceback is # available. self._RecordResult(result) # Ask the execution engine to stop running tests. if self.__engine: self.__engine.RequestTermination() # Re-raise the exception. raise except self.__ResourceSetUpException, e: result.SetOutcome(Result.UNTESTED) result[Result.CAUSE] = qm.message("failed resource") result[Result.RESOURCE] = e.resource except: result.NoteException() # Record the result. self._RecordResult(result) def _RecordResult(self, result): """Record the 'result'. 'result' -- A 'Result' of a test or resource execution. Derived classes may override this method, but the overriding method must call this method at some point during its execution.""" # Record the target in the result. result[Result.TARGET] = self.GetName() # Put the result into the response queue. self.__response_queue.put(result) def _BeginResourceSetUp(self, resource_name): """Begin setting up the indicated resource. 'resource_name' -- A string naming a resource. returns -- If at attempt to set up the resource has already been made, returns a tuple '(resource, outcome, properties)'. The 'resource' is the 'Resource' object itself, but may be 'None' if the resource could not be set up. The 'outcome' indicates the outcome that resulted when the resource was set up. The 'properties' are a map from strings to strings indicating properties added by this resource. If the resource has not been set up, but _BeginResourceSetUp has already been called for the resource, then the contents of the tuple will all be 'None'. If this is the first time _BeginResourceSetUp has been called for this resource, then 'None' is returned, but the resource is marked as in the process of being set up. It is the caller's responsibility to finish setting it up by calling '_FinishResourceSetUp'.""" rop = self.__resources.get(resource_name) if rop: return rop self.__resources[resource_name] = (None, None, None) return None def _FinishResourceSetUp(self, resource, result, properties): """Finish setting up a resource. 'resource' -- The 'Resource' itself. 'result' -- The 'Result' associated with setting up the resource. 'properties' -- A dictionary of additional context properties that should be provided to tests that depend on this resource. returns -- A tuple of the same form as is returned by '_BeginResourceSetUp' when the resource has already been set up.""" # The temporary directory is not be preserved; there is no # guarantee that it will be the same in a test that depends on # this resource as it was in the resource itself. del properties[Context.TMPDIR_CONTEXT_PROPERTY] rop = (resource, result.GetOutcome(), properties) self.__resources[result.GetId()] = rop self.__order_of_resources.append(result.GetId()) return rop def __SetUpResources(self, descriptor, context): """Set up all the resources associated with 'descriptor'. 'descriptor' -- The 'TestDescriptor' or 'ResourceDescriptor' indicating the test or resource that is about to be run. 'context' -- The 'Context' in which the resources will be executed. returns -- A tuple of the same form as is returned by '_BeginResourceSetUp' when the resource has already been set up.""" # See if there are resources that need to be set up. for resource in descriptor.GetResources(): (r, outcome, resource_properties) \ = self._SetUpResource(resource, context) # If the resource was not set up successfully, # indicate that the test itself could not be run. if outcome != Result.PASS: raise self.__ResourceSetUpException, resource # Update the list of additional context properties. context.update(resource_properties) return context def _SetUpResource(self, resource_name, context): """Set up the resource given by 'resource_id'. 'resource_name' -- The name of the resource to be set up. 'context' -- The 'Context' in which to run the resource. returns -- A map from strings to strings indicating additional properties added by this resource.""" # Begin setting up the resource. rop = self._BeginResourceSetUp(resource_name) # If it has already been set up, there is no need to do it # again. if rop: return rop # Set up the context. wrapper = Context(context) result = Result(Result.RESOURCE_SETUP, resource_name, Result.PASS) resource = None # Get the resource descriptor. try: resource_desc = self.GetDatabase().GetResource(resource_name) # Set up the resources on which this resource depends. self.__SetUpResources(resource_desc, wrapper) # Make the ID of the resource available. wrapper[Context.ID_CONTEXT_PROPERTY] = resource_name # Set up the resource itself. try: resource_desc.SetUp(wrapper, result) finally: del wrapper[Context.ID_CONTEXT_PROPERTY] # Obtain the resource within the try-block so that if it # cannot be obtained the exception is handled below. resource = resource_desc.GetItem() except self.__ResourceSetUpException, e: result.Fail(qm.message("failed resource"), { result.RESOURCE : e.resource }) except NoSuchResourceError: result.NoteException(cause="Resource is missing from the database.") self._RecordResult(result) return (None, result, None) except qm.test.base.CouldNotLoadExtensionError, e: result.NoteException(e.exc_info, cause = "Could not load extension class") except KeyboardInterrupt: result.NoteException() # We received a KeyboardInterrupt, indicating that the # user would like to exit QMTest. Ask the execution # engine to stop. if self.__engine: self.__engine.RequestTermination() except: result.NoteException() # Record the result. self._RecordResult(result) # And update the table of available resources. return self._FinishResourceSetUp(resource, result, wrapper.GetAddedProperties()) def _CleanUpResource(self, name, resource): """Clean up the 'resource'. 'resource' -- The 'Resource' that should be cleaned up. 'name' -- The name of the resource itself.""" result = Result(Result.RESOURCE_CLEANUP, name) # Clean up the resource. try: val = resource.CleanUp(result) except: result.NoteException() self._RecordResult(result) def _GetTemporaryDirectory(self): """Return the path to a temporary directory. returns -- The path to a temporary directory to pass along to tests and resources via the 'TMPDIR_CONTEXT_PROPERTY'.""" raise NotImplementedError qmtest-2.4.1/qm/test/parameter_database.py0000664000076400007640000002635611107032225020146 0ustar stefanstefan######################################################################## # # File: parameter_database.py # Author: Stefan Seefeld # Date: 2005-01-17 # # Contents: # Test database that parametrizes another test database.. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## from qm.test.database import * from qm.test.suite import * ######################################################################## # classes ######################################################################## class ParameterDatabase(Database): """A database that parametrizes another database. 'Parameter' in this context refers to any name that is used as a label, and which stands for a specific set of arguments passed to tests. The 'ParameterDatabase' class is abstract. Subclasses need to implement the '_GetParametersForTest' as well as the '_GetArgumentsForParameter' method. """ class ImplicitSuite(Suite): """ImplicitSuite represents a suite obtained from a test and a set of parameters applied to it.""" def __init__(self, db, suite_id): Suite.__init__(self, {}, qmtest_id = suite_id, qmtest_database = db) def GetTestIds(self): database = self.GetDatabase() id = self.GetId() return map(lambda p, db = database, id = id: db.JoinLabels(id, p), database._GetParametersForTest(id)) def IsImplicit(self): return True class WrapperSuite(Suite): """As tests from the wrapped Database are mapped to suites, suites from the wrapped Database have to be recreated with all tests replaced by ImplicitSuite instances. Additionally, new (explicit) suites may be added.""" def __init__(self, db, suite, suite_ids = None): """Take over suite_ids from the wrapped database but replace test_ids by suite_ids if there are parameters available for them.""" Suite.__init__(self, {}, qmtest_id = suite.GetId(), qmtest_database = db) self.__suite = suite self.__suite_ids = suite_ids or [] def GetSuiteIds(self): suite_ids = self.__suite.GetSuiteIds() for t in self.__suite.GetTestIds(): if self.GetDatabase()._GetParametersForTest(t): suite_ids.append(t) return suite_ids + self.__suite_ids def GetTestIds(self): test_ids = [] for t in self.__suite.GetTestIds(): if not self.GetDatabase()._GetParametersForTest(t): test_ids.append(t) return test_ids def IsImplicit(self): return self.__suite.IsImplicit() def GetAllTestAndSuiteIds(self): db = self.GetDatabase() orig_test_ids, suite_ids = self.__suite.GetAllTestAndSuiteIds() test_ids = [] for test in orig_test_ids: parameters = db._GetParametersForTest(test) if parameters: suite_ids.append(test) test_ids.extend(map(lambda p, test=test, db=db: db.JoinLabels(test, p), parameters)) else: test_ids.append(test) return test_ids, suite_ids + self.__suite_ids class ParameterSuite(Suite): """ParameterSuite represents a suite obtained from applying a given parameter to a suite from the wrapped DB.""" def __init__(self, database, suite, parameter): """Construct a ParameterSuite. database -- The database this suite refers to. suite -- The original suite this suite parametrizes. parameter -- The value for the parameter to apply to the suite.""" Suite.__init__(self, {}, qmtest_id = database.JoinLabels(suite.GetId(), parameter), qmtest_database = database) self.__suite = suite self.__parameter = parameter def GetSuiteIds(self): """ParameterSuites contain ParameterSuites which wrap suites contained in the wrapped suite.""" database = self.GetDatabase() return map(lambda id, db = database, p = self.__parameter: db.JoinLabels(id, p), self.__suite.GetSuiteIds()) def GetTestIds(self): """ParameterSuites contain Tests obtained by applying the given parameter set to the tests contained in the wrapped suite.""" database = self.GetDatabase() return map(lambda id, db = database, p = self.__parameter: db.JoinLabels(id, p), self.__suite.GetTestIds()) def IsImplicit(self): return False def __init__(self, database, path, arguments): self.label_class = database.label_class Database.__init__(self, path, arguments) self.__db = database def GetWrappedDatabase(self): return self.__db def _GetParametersForTest(self, test_id): """Return a list of parameters that can be applied to the test 'test_id'.""" return [] def _GetArgumentsForParameter(self, test_id, parameter): """Return the set of arguments for this parameter. 'test_id' -- The test id to which the parameter belongs. 'parameter' -- The parameter for which the arguments are queried. returns -- A dictionary containing the argument as name/value pairs.""" return {} def GetTest(self, test_id): directory, basename = self.SplitLabel(test_id) if not self.HasTest(test_id): raise NoSuchTestError, test_id test = self.__db.GetTest(directory) # now generate a new test arguments = test.GetArguments() #override parameters arguments.update(self._GetArgumentsForParameter(directory, basename)) return TestDescriptor(self, test_id, test.GetClassName(), arguments) def HasTest(self, test_id): # If test_id is a parametrized test, its basename has to refer to # a parameter set and the directory to a test in the wrapped DB. # # Else basename must not be a parameter set, and test_id a test # in the wrapped DB. directory, basename = self.SplitLabel(test_id) return (basename in self._GetParametersForTest(directory) and self.__db.HasTest(directory) or self.__db.HasTest(test_id)) def GetTestIds(self, directory="", scan_subdirs=1): # directory may be a test in the wrapped DB... if self.__db.HasTest(directory): ids = [directory] # ...or a directory, in which case we only take it into account # if scan_subdirs == 1. elif scan_subdirs: ids = self.__db.GetTestIds(directory, scan_subdirs) else: return [] tests = [] for p in self._GetParametersForTest(directory): tests += map(lambda x, p = p, db = self: db.JoinLabels(x, p), ids) return tests def GetSuite(self, suite_id): # If suite_id refers to a suite in the WD, wrap it. if self.__db.HasSuite(suite_id): return ParameterDatabase.WrapperSuite(self, self.__db.GetSuite(suite_id)) # If suite_id refers to a test in the WD, parametrize it. elif self.__db.HasTest(suite_id): return ParameterDatabase.ImplicitSuite(self, suite_id) raise NoSuchSuiteError, suite_id def HasSuite(self, suite_id): directory, basename = self.SplitLabel(suite_id) return (basename in self._GetParametersForTest(directory) and self.__db.HasSuite(directory) or self.__db.HasSuite(suite_id) or self.__db.HasTest(suite_id)) def GetSuiteIds(self, directory="", scan_subdirs=1): if self.__db.HasTest(directory): return [] suite_ids = self.__db.GetSuiteIds(directory, scan_subdirs) test_ids = self.__db.GetTestIds(directory, scan_subdirs) param_ids = map(lambda p, d = directory, db = self: db.JoinLabels(d, p), self._GetParametersForTest(directory)) # The set of all (non-recursive) suite ids is composed of the # original suite ids plus original test ids (now being suite ids) # as well as explicit suites obtained by combining the given # directory with all parameters. ids = suite_ids + test_ids + param_ids if not scan_subdirs: return ids else: # The set of all suite ids is composed of the set above plus # everything above combined with all parameters. expl_ids = [] for p in self._GetParametersForTest(directory): expl_ids += map(lambda x, p = p, db = self: db.JoinLabels(x, p), suite_ids + test_ids) return ids + expl_ids def GetResource(self, resource_id): return self.__db.GetResource(resource_id) def HasResource(self, resource_id): return self.__db.HasResource(resource_id) def GetResourceIds(self, directory="", scan_subdirs=1): if self.__db.HasTest(directory): return [] return self.__db.GetResourceIds(directory, scan_subdirs) def GetIds(self, kind, directory="", scan_subdirs = 1): if kind == Database.TEST: return GetTestIds(directory, scan_subdirs) return self.__db.GetIds(kind, directory, scan_subdirs) def GetSubdirectories(self, directory): # GetSubdirectories returns the subdirectories of the given directory. # As this Database turns all tests from the wrapped Database into # ImplicitSuites, we have to account for them here. # # Further, while 'directory' has to be a directory when looked at it # from this Database, it may well be a test in the context of the wrapped # Database, in which case it can't have subdirectories. if self.__db.HasTest(directory): return [] subdirs = self.__db.GetSubdirectories(directory) subdirs += [d[directory and len(directory) + 1:] # Remove common prefix. for d in self.__db.GetTestIds(directory, False)] return subdirs def GetAttachmentStore(self): return self.__db.GetAttachmentStore() def GetClassPath(self): return self.__db.GetClassPath() def GetTestClassNames(self): return self.__db.GetTestClassNames() def GetResourceClassNames(self): return self.__db.GetResourceClassNames() qmtest-2.4.1/qm/test/__init__.py0000664000076400007640000000126211107032225016066 0ustar stefanstefan######################################################################## # # File: __init__.py # Author: Alex Samuel # Date: 2001-03-08 # # Contents: # qm.test module initialization. # # Copyright (c) 2001 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/result_reader.py0000664000076400007640000000341711107032225017173 0ustar stefanstefan######################################################################## # # File: result_reader.py # Author: Nathaniel Smith # Date: 2003-06-23 # # Contents: # QMTest ResultReader class. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm.extension ######################################################################## # Classes ######################################################################## class ResultReader(qm.extension.Extension): """A 'ResultReader' provides access to stored test results. For instance, a 'ResultReader' may load 'Result's from a pickle file or an XML file. This is an abstract class. See also 'ResultStream'.""" kind = "result_reader" def __init__(self, arguments, **args): if arguments: args.update(arguments) super(ResultReader, self).__init__(**args) def GetAnnotations(self): """Return this run's dictionary of annotations.""" # For backwards compatibility, don't raise an exception. return {} def GetResult(self): """Return the next 'Result' from this reader. returns -- A 'Result', or 'None' if there are no more results. """ raise NotImplementedError def __iter__(self): """A 'ResultReader' can be iterated over.""" return iter(self.GetResult, None) ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/resource.py0000664000076400007640000001007611107032225016161 0ustar stefanstefan######################################################################## # # File: resource.py # Author: Mark Mitchell # Date: 2001-10-10 # # Contents: # QMTest Resource class. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm import qm.test.runnable ######################################################################## # Classes ######################################################################## class Resource(qm.test.runnable.Runnable): """A 'Resource' sets up before a test and cleans up afterwards. Some tests take a lot of work to set up. For example, a database test that checks the result of SQL queries may require that the database first be populated with a substantial number of records. If there are many tests that all use the same set of records, it would be wasteful to set up the database for each test. It would be more efficient to set up the database once, run all of the tests, and then remove the databases upon completion. You can use a 'Resource' to gain this efficiency. If a test depends on a resource, QMTest will ensure that the resource is available before the test runs. Once all tests that depend on the resource have been run QMTest will destroy the resource. Each resource class (i.e., class derived from 'Resource') describes a set of "arguments". Each argument has a name and a type. The values of these arguments determine the design-time parameters for the resource. See the documentation for the 'Test' class for more complete information. Each resource class also defines a 'SetUp' method that indicates how to set up the resource, and a 'CleanUp' method that indicates how to clean up afterwards. 'Resource' is an abstract class. You can extend QMTest by providing your own resource class implementation. If the resource classes that come with QMTest cannot be used conveniently with your application domain, you may wish to create a new resource class. To create your own resource class, you must create a Python class derived (directly or indirectly) from 'Resource'. The documentation for each method of 'Resource' indicates whether you must override it in your resource class implementation. Some methods may be overridden, but do not need to be. You might want to override such a method to provide a more efficient implementation, but QMTest will work fine if you just use the default version. If QMTest calls a method on a resource and that method raises an exception that is not caught within the method itself, QMTest will catch the exception and continue processing.""" kind = "resource" def SetUp(self, context, result): """Set up the resource. 'context' -- A 'Context' giving run-time parameters to the resource. The resource may place additional variables into the 'context'; these variables will be visible to tests that depend on the resource. 'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations. This method should not return a value. Derived classes must override this method.""" raise NotImplementedError def CleanUp(self, result): """Clean up the resource. 'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations. This method should not return a value. Derived classes may override this method.""" pass qmtest-2.4.1/qm/test/context.py0000664000076400007640000002444411107032225016022 0ustar stefanstefan######################################################################## # # File: context.py # Author: Mark Mitchell # Date: 11/06/2001 # # Contents: # QMTest Context class # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm import qm.common import re import sys import types ######################################################################## # Classes ######################################################################## class ContextException(qm.common.QMException): """A 'ContextException' indicates an invalid context variable.""" def __init__(self, key, msg = "missing context variable"): """Construct a new 'ContextException'. 'key' -- A string giving the context key for which no valid value was available. 'msg' -- A diagnostic identifier explaining the problem. The message string may contain a fill-in for the key.""" msg = qm.error(msg, key = key) qm.common.QMException.__init__(self, msg) self.key = key class ContextWrapper: """Do-nothing class to preserve pickle compatability. A class called 'ContextWrapper' used to be used in instead of a 'Context' class in some cases, and we used to put contexts into 'Result's. Because of how pickles work, this means that the only way to unpickle these old 'Result's is to have a do-nothing placeholder class that can be instantiated and then thrown away.""" pass class Context(types.DictType): """Test-time and local configuration for tests. A 'Context' object contains all of the information a test needs to execute, beyond what is stored as part of the test specification itself. Information in the context can include, * Local (per-user, etc.) configuration, such as where to find the tested program. * Environmental information, such as which machine the test is running on. * One-time configuration, including test arguments specified on the command line. A 'Context' object is effectively a mapping object whose keys must be labels and values must be strings.""" TARGET_CONTEXT_PROPERTY = "qmtest.target" """The context variable giving the name of the current target.""" DB_PATH_CONTEXT_PROPERTY = "qmtest.dbpath" """The context variable giving the path to the database. The value of this context variable will be a string giving the path to the database directory. For example, if QMTest is invoked as 'qmtest -D /path/to/db run', the value of this variable would be '/path/to/db'. The value may be an absolute or a relative path.""" ID_CONTEXT_PROPERTY = "qmtest.id" """The context variable giving the name of the running test or resource. This value of this context variable will be the string giving the name of the of the test or resource that is presently executing.""" TMPDIR_CONTEXT_PROPERTY = "qmtest.tmpdir" """A context property whose value is a string giving the path to a temporary directory. This directory will be used only by the 'Runnable' in whose context this property occurs during the execution of that 'Runnable'. No other object will use the same temporary directory at the same time. There is no guarantee that the temporary directory is empty, however; it may contain files left behind by the execution of other 'Runnable' objects.""" __safe_for_unpickling__ = 1 """Required to unpickle new-style classes under Python 2.2.""" def __init__(self, context = None): """Construct a new context. 'context' -- If not 'None', the existing 'Context' being wrapped by this new context.""" super(Context, self).__init__() self.__context = context # Stuff everything in the RC configuration into the context. options = qm.rc.GetOptions() for option in options: value = qm.rc.Get(option, None) assert value is not None self[option] = value def GetDerivedValue(self, klass, variable, default = None): """Return the value for 'variable' in scope 'klass'. Scopes are nested with '.', and inner variables hide outer variables of the same name. Thus, looking up the value of 'a.b.c.var' will return 1 if the context contains a.b.c.var=1 but 2 if it contains a.b.d.var=1 a.b.var=2 a.var=3. 'klass' -- The variable's scope. 'variable' -- The variable name. 'default' -- Default value.""" while True: if klass: k = klass + '.' + variable else: k = variable if self.has_key(k): return self[k] if not klass: return default if '.' not in klass: klass = '' else: klass = klass[0:klass.rfind('.')] def GetBoolean(self, key, default = None): """Return the boolean value associated with 'key'. 'key' -- A string. 'default' -- A default boolean value. returns -- The value associated with 'key' in the context, interpreted as a boolean. If there is no value associated with 'key' and default is not 'None', then the boolean value associated with default is used. If there is no value associated with 'key' and default is 'None', an exception is raised. The value associated with 'key' must be a string. If not, an exception is raised. If the value is a string, but does not correspond to a boolean value, an exception is raised.""" valstr = self.get(key) if valstr is None: if default is None: raise ContextException(key) else: return default try: return qm.common.parse_boolean(valstr) except ValueError: raise ContextException(key, "invalid boolean context var") def GetStringList(self, key, default = None): """Return the list of strings associated with 'key'. 'key' -- A string. 'default' -- A default list. If there is no value associated with 'key' and default is not 'None', then the boolean value associated with default is used. If there is no value associated with 'key' and default is 'None', an exception is raised. The value associated with 'key' must be a string. If not, an exception is raised. If the value is a string, but does not correspond to a string list, an exception is raised. """ valstr = self.get(key) if valstr is None: if default is None: raise ContextException(key) else: return default try: return qm.common.parse_string_list(valstr) except ValueError: raise ContextException(key, "invalid string list context var") def GetTemporaryDirectory(self): """Return the path to the a temporary directory. returns -- The path to the a temporary directory. The 'Runnable' object may make free use of this temporary directory; no other 'Runnable's will use the same directory at the same time.""" return self[self.TMPDIR_CONTEXT_PROPERTY] def Read(self, file_name): """Read the context file 'file_name'. 'file_name' -- The name of the context file. Reads the context file and adds the context properties in the file to 'self'.""" if file_name == "-": # Read from standard input. file = sys.stdin else: # Read from a named file. try: file = open(file_name, "r") except: raise qm.cmdline.CommandError, \ qm.error("could not read file", path=file_name) # Read the assignments. assignments = qm.common.read_assignments(file) # Add them to the context. for (name, value) in assignments.items(): try: # Insert it into the context. self[name] = value except ValueError, msg: # The format of the context key is invalid, but # raise a 'CommandError' instead. raise qm.cmdline.CommandError, msg # Methods to simulate a map object. def __contains__(self, key): if super(Context, self).__contains__(key): return 1 if self.__context is not None: return self.__context.__contains__(key) return 0 def get(self, key, default = None): if key in self: return self[key] return default def has_key(self, key): return key in self def __getitem__(self, key): try: return super(Context, self).__getitem__(key) except KeyError: if self.__context is None: raise ContextException(key) try: return self.__context[key] except KeyError: raise ContextException(key) def items(self): if self.__context is None: return super(Context, self).items() else: # Have to be careful, because self.__context and self may # contain different values for the same keys, and the values # defined in self should override the values defined in # self.__context. unified_dict = dict(self.__context.items()) unified_dict.update(self) return unified_dict.items() # Helper methods. def GetAddedProperties(self): """Return the properties added to this context by resources. returns -- A map from strings to values indicating properties that were added to this context by resources.""" if self.__context is None: return {} added = self.__context.GetAddedProperties() added.update(self) return added qmtest-2.4.1/qm/test/test_run.py0000664000076400007640000000771611107032225016204 0ustar stefanstefan######################################################################## # # File: test_run.py # Author: Mark Mitchell # Date: 2005-08-08 # # Contents: # QMTest TestRun class. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.test.result import Result ######################################################################## # Classes ######################################################################## class TestRun(object): """A 'TestRun' stores the 'Result's from a single test run. The primary contents of a 'TestRun' are the the 'Result's of the run. In addition, each 'TestRun' has an associated set of annotations, which are used to store global information about the 'TestRun'.""" def GetResult(self, id, kind = Result.TEST): """Return the 'Result' for the indicated test. 'id' -- The name of a test or resource. 'kind' -- The kind of result to retrieve. See 'Result' for a list of the available result kinds. returns -- The 'Result' corresponding to 'test_id'. raises -- 'KeyError' if there is no result of the given 'kind' for 'id' in the test run.""" raise NotImplementedError def GetAnnotation(self, key): """Return the annotation associated with 'key'. 'key' -- A string giving the name of an annotation. returns -- A string giving the value of the annotation, or 'None' if there is no such annotation.""" raise NotImplementedError def GetAnnotations(self): """Return this run's dictionary of annotations. returns -- A dictionary mapping annotation names (strings) to values (also strings).""" raise NotImplementedError def GetAllResults(self, directory = "", kind = Result.TEST): """Return 'Result's from the given directory.. 'directory' -- A path to a directory in the test database. 'kind' -- The kind of results to return. returns -- All the results within 'directory' (including its subdirectories).""" raise NotImplementedError def GetResultsByOutcome(self, outcome = None, directory = "", kind = Result.TEST): """Return 'Result's with a particular outcome. 'outcome' -- One of the 'Result.outcomes', or 'None'. 'directory' -- A path to a directory in the test database. 'kind' -- The kind of results to return. returns -- All the results within 'directory' (including its subdirectories) that have the indicated 'outcome', or, if 'outcome' is 'None', all test results from 'directory'.""" results = [] for result in self.GetAllResults(directory, kind): # Check the outcome. if outcome and result.GetOutcome() != outcome: continue results.append(result) return results def CountOutcomes(self, directory = "", outcome = None): """Return statistics about the outcomes of tests. 'directory' -- A path to a directory in the test database. 'outcome' -- If not 'None', one of the 'Result.outcomes'. returns -- A dictionary mapping outcomes to the number of test results with that outcome located within 'directory' and its subdirectories. If 'outcome' is not 'None', the dictionary will have an entry only for the 'outcome' specified.""" if not outcome: outcomes = Result.outcomes else: outcomes = (outcome,) counts = {} for o in outcomes: counts[o] = len(self.GetResultsByOutcome(o, directory)) return counts qmtest-2.4.1/qm/test/database.py0000664000076400007640000011717011107032225016101 0ustar stefanstefan######################################################################## # # File: database.py # Author: Mark Mitchell # Date: 2001-10-05 # # Contents: # QMTest database class. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import os.path import qm from qm.common import * import qm.extension import qm.fields from qm.label import * from qm.test.base import * from qm.test.directory_suite import DirectorySuite from qm.test.runnable import Runnable from qm.test.resource import Resource from qm.test.suite import Suite from qm.test.test import Test ######################################################################## # Variables ######################################################################## __the_database = None """The global 'Database' object.""" __the_db_path = '.' """The path to the database.""" ######################################################################## # Classes ######################################################################## class ItemDescriptor: """An 'ItemDescriptor' describes a test, resource, or similar entity. Some 'Database' operations return an instance of a class derived from 'ItemDescriptor', rather than the object described. For example, 'Database.GetTest' returns a 'TestDescriptor', not a 'Test'. This additional indirection is an optimization; the creation of the actual 'Test' object may be relatively expensive, and in many cases all that is needed is information that can be gleaned from the descriptor.""" def __init__(self, database, instance_id, class_name = None, arguments = None, item = None): """Construct an 'ItemDescriptor'. 'database' -- The 'Database' object in which this entity is located. 'instance_id' -- The label for this entity. 'class_name' -- The name of the extension class for the entity. For example, for a 'TestDescriptor', the 'class_name' is the name of the test class. Omit this argument if 'item' is provided. 'arguments' -- A dictionary mapping argument names to argument values. These arguments will be provided to the extension class when the entity is constructed. Omit this argument if 'item' is provided. 'item' -- The item class for this item instance.""" self.__database = database self.__id = instance_id assert(not item or not class_name) self.__class_name = class_name self.__arguments = arguments self._item = item def GetDatabase(self): """Return the 'Database' containing this entity. returns -- The 'Database' object in which this entity is located.""" return self.__database def GetClassName(self): """Return the class name of the entity. returns -- The name of the extension class for the entity. For example, for a 'TestDescriptor', this method returns the name of the test class.""" if self._item: return self._item.GetClassName() else: return self.__class_name def GetClass(self): """Return the class of the entity. returns -- The Python class object for the entity. For example, for a 'TestDescriptor', this method returns the test class.""" raise NotImplementedError def GetClassArguments(self): """Return the arguments specified by the test class. returns -- A list of 'Field' objects containing all the arguments in the class hierarchy. Derived classes should not override this method.""" return qm.extension.get_class_arguments(self.GetClass()) def GetArguments(self): """Return the entity arguments. returns -- A dictionary mapping argument names to argument values. These arguments will be provided to the extension class when the entity is constructed.""" if self._item: return self._item.GetExplicitArguments() else: return self.__arguments def GetId(self): """Return the label for this entity. returns -- The label for this entity.""" return self.__id def GetItem(self): """Return the entity. returns -- An instance of the class returned by 'GetClass'.""" if not self._item: extras = { Runnable.EXTRA_ID : self.GetId(), Runnable.EXTRA_DATABASE : self.GetDatabase() } self._item = self.GetClass()(self.GetArguments(), **extras) return self._item def GetResources(self): """Return the resources required by this item. returns -- A sequence of resource names. Each name indicates a resource that must be available to this item.""" return self.GetArguments().get(Runnable.RESOURCE_FIELD_ID, []) # Helper functions. def _Execute(self, context, result, method): """Execute the entity. 'context' -- The 'Context' in which the test should be executed, or 'None' if the 'method' does not take a 'Context' argument. 'result' -- The 'Result' object corresponding to this execution. 'method' -- The method name of the method on the entity that should be invoked to perform the execution.""" # Get the item. item = self.GetItem() methobj = getattr(item, method) # Execute the indicated method. if context is not None: methobj(context, result) else: methobj(result) class TestDescriptor(ItemDescriptor): """A test instance.""" def __init__(self, database, test_id, test_class_name = None, arguments = None, test = None): """Create a new test instance. 'database' -- The 'Database' containing this test. 'test_id' -- The test ID. 'test_class_name' -- The name of the test class of which this is an instance. Omit this argument if 'test' is provided. 'arguments' -- This test's arguments to the test class. Omit this argument if 'test' is provided. 'test' -- The test class of which this is an instance.""" # Initialize the base class. ItemDescriptor.__init__(self, database, test_id, test_class_name, arguments, test) self.__prerequisites = {} for p, o in \ self.GetArguments().get(Test.PREREQUISITES_FIELD_ID, []): self.__prerequisites[p] = o def GetClass(self): """Return the class of the entity. returns -- The Python class object for the entity. For example, for a 'TestDescriptor', this method returns the test class.""" if self._item: return type(self._item) return get_extension_class(self.GetClassName(), 'test', self.GetDatabase()) def GetTest(self): """Return the 'Test' object described by this descriptor.""" return self.GetItem() def GetPrerequisites(self): """Return a map from prerequisite test IDs to required outcomes.""" return self.__prerequisites def GetTargetGroup(self): """Returns the pattern for the targets that can run this test. returns -- A regular expression (represented as a string) that indicates the targets on which this test can be run. If the pattern matches a particular group name, the test can be run on targets in that group.""" return self.GetArguments().get("target_group", ".*") def Run(self, context, result): """Execute this test. 'context' -- The 'Context' in which the test should be executed. 'result' -- The 'Result' object for this test.""" self._Execute(context, result, "Run") class ResourceDescriptor(ItemDescriptor): """A resource instance.""" def __init__(self, database, resource_id, resource_class_name = None, arguments = None, resource = None): """Create a new resource instance. 'database' -- The 'Database' containing this resource. 'resource_id' -- The resource ID. 'resource_class_name' -- The name of the resource class of which this is an instance. Omit this argument if 'resource' is provided. 'arguments' -- This resource's arguments to the resource class. Omit this argument if 'resource' is provided. 'resource' -- The resource class of which this is an instance.""" # Initialize the base class. ItemDescriptor.__init__(self, database, resource_id, resource_class_name, arguments, resource) def GetClass(self): """Return the class of the entity. returns -- The Python class object for the entity. For example, for a 'TestDescriptor', this method returns the test class.""" if self._item: return type(self._item) return get_extension_class(self.GetClassName(), 'resource', self.GetDatabase()) def GetResource(self): """Return the 'Resource' object described by this descriptor.""" return self.GetItem() def SetUp(self, context, result): """Set up the resource. 'context' -- The 'Context' in which the resource should be executed. 'result' -- The 'Result' object for this resource.""" self._Execute(context, result, "SetUp") def CleanUp(self, result): """Clean up the resource. 'result' -- The 'Result' object for this resource.""" self._Execute(None, result, "CleanUp") class DatabaseError(QMException): """An exception relating to a 'Database'. All exceptions raised directly by 'Database', or its derived classes, will be instances of 'DatabaseError', or a class derived from 'DatabaseError'. If QMTest catches the exception, it will treat the string representation of the exception as an error message to be formatted for the user.""" class NoSuchItemError(DatabaseError): """An exception indicating that a particular item could not be found.""" def __init__(self, kind, item_id): self.kind = kind self.item_id = item_id def __str__(self): """Return a string describing this exception.""" return qm.message("no such item", kind = self.kind, item_id = self.item_id) class NoSuchTestError(NoSuchItemError): """The specified test does not exist.""" def __init__(self, test_id): """Construct a new 'NoSuchTestError' 'test_id' -- The name of the test that does not exist.""" NoSuchItemError.__init__(self, Database.TEST, test_id) class NoSuchSuiteError(NoSuchItemError): """The specified suite does not exist.""" def __init__(self, suite_id): """Construct a new 'NoSuchSuiteError' 'suite_id' -- The name of the suite that does not exist.""" NoSuchItemError.__init__(self, Database.SUITE, suite_id) class NoSuchResourceError(NoSuchItemError): """The specified resource does not exist.""" def __init__(self, resource_id): """Construct a new 'NoSuchResourceError' 'resource_id' -- The name of the resource that does not exist.""" NoSuchItemError.__init__(self, Database.RESOURCE, resource_id) class Database(qm.extension.Extension): """A 'Database' stores tests, testsuites, and resources. A 'Database' has two primary functions: 1. Test storage and retrieval. Every test has a unique name, called a "test id". When a new test is created, the 'Database' is responsible for writing that test to permanent storage. Later, QMTest will request the test by providing the database with the test id. The database must retrieve the test from permanent storage. QMTest does not put any restrictions on *how* tests are stored. The default database implementation uses XML to store tests, but any storage format will do. 2. Test enumeration. The 'Database' can tell QMTest what tests are stored in the database. QMTest uses this information in its graphical user interface to show the user what tests exist. A 'Database' stores testsuites and resources in addition to tests. The names for tests, testsuites, and resources are all "labels". A label is a special kind of string that is designed to be easily convertible to a file name. For more information, see the 'qm.label' module. The namespaces for tests, testsuites, and resources are all distinct. For example, it is OK to have a test with the same name as a testsuite. Every 'Database' is associated with a particular directory on the local machine. In most cases, the 'Database' will store all the files it needs within this directory. Every 'Database' has an associated 'AttachmentStore'. An 'AttachmentStore' is responsible for storing the attachments associated with tests. See the module 'qm.attachment' for more information about 'AttachmentStore'. 'Database' is an abstract class. You can extend QMTest by providing your own database implementation. One reason to do this is that you may want to store tests in a format different from the XML format that QMTest uses by default. For example, if you are testing a compiler, you might want to represent each test as a source file. Or, if you are testing a SQL database, you might want to represent each test as two files: one containing SQL commands to run the test, and one containing the output you expect. Another reason to provide your own database implementation is that you might want to store tests on a remote location. For example, suppose you wanted to allow multiple users to access the same central test database. You could create a test database that created and retrieved tests by communicating with the central server. To create your own database implementation, you must create a Python class derived (directly or indirectly) from 'Database'. The documentation for each method of 'Database' indicates whether you must override it in your database implementation. Some methods may be overridden, but do not need to be. You might want to override such a method to provide a more efficient implementation, but QMTest will work fine if you just use the default version. If QMTest calls a method on a database and that method raises an exception that is not caught within the method itself, QMTest will catch the exception and continue processing. Therefore, methods here only have to handle exceptions themselves if that is necessary to maintain the integrity of the database. A single 'Database' may be accessed by multiple threads simultaneously. Therefore, you must take appropriate steps to ensure thread-safe access to shared data.""" arguments = [ qm.fields.TextField( name = "label_class", title = "Label Class", description = """The name of the label class used by this database. The label class is used to separate names of entities used by the database into directories and basenames.""", default_value = "python_label.PythonLabel" ), qm.fields.BooleanField( name = "modifiable", title = "Modifiable?", description = """Whether or not the database can be modified. If true, changes (such as the addition or removal of tests, resources, or suites) can be made to the test database. If false, tests can be viewed and run, but not modified.""", default_value = "true") ] RESOURCE = "resource" SUITE = "suite" TEST = "test" ITEM_KINDS = [RESOURCE, SUITE, TEST] """The kinds of items that can be stored in a 'Database'.""" _item_exceptions = { RESOURCE : NoSuchResourceError, SUITE : NoSuchSuiteError, TEST : NoSuchTestError } """The exceptions to be raised when a particular item cannot be found. This map is indexed by the 'ITEM_KINDS'; the value indicates the exception class to be used when the indicated kind cannot be found.""" _is_generic_database = False """True if this database implements 'GetExtension' as a primitive. Databases should implement 'GetExtension' and then override '_is_generic_database', setting it to 'True'. However, legacy databases implemented 'GetTest', 'GetResource', and 'GetSuite' as primivites. These legacy databases should not override '_generic_database'.""" kind = "database" """The 'Extension' kind.""" def __init__(self, path, arguments = None, **args): """Construct a 'Database'. 'path' -- A string containing the absolute path to the directory containing the database. 'arguments' -- A dictionary mapping attribute names to values. The use of this parameter is deprecated. Use keyword arguments instead. Derived classes must call this method from their own '__init__' methods. Every derived class must have an '__init__' method that takes the path to the directory containing the database as its only argument. The path provided to the derived class '__init__' function will always be an absolute path.""" if arguments: args.update(arguments) qm.extension.Extension.__init__(self, **args) # The path given must be an absolute path. assert os.path.isabs(path) self.__path = path # Translate the label class name into an actual Python class. self.__label_class \ = get_extension_class(self.label_class, "label", self) # Methods that deal with labels. def IsValidLabel(self, label, is_component = 1): """Return true if 'label' is valid. 'label' -- A string that is being considered as a label. 'is_component' -- True if the string being tested is just a single component of a label path. returns -- True if 'label' is a valid name for entities in this database.""" return self.__label_class("").IsValid(label, is_component) def JoinLabels(self, *labels): """Join the 'labels' together. 'labels' -- A sequence of strings corresponding to label components. returns -- A string containing the complete label.""" if not labels: return "" return str(apply(self.__label_class(labels[0]).Join, labels[1:])) def SplitLabel(self, label): """Split the label into a pair '(directory, basename)'. returns -- A pair of strings '(directory, basename)'.""" return map(str, self.__label_class(label).Split()) def SplitLabelLeft(self, label): """Split the label into a pair '(parent, subpath)'. This is the same operation as SplitLabel, except the split occurs at the leftmost separator, not the rightmost, and a single-component label comes back in the parent slot. returns -- A pair of strings '(parent, subpath)'.""" return map(str, self.__label_class(label).SplitLeft()) def GetLabelComponents(self, label): """Return all of the component directories of 'label'. 'label' -- A string naming an entity in the database. returns -- A list of strings. The first string is the first directory in 'label'; the last string is the basename.""" components = [] while label: dirname, label = self.SplitLabelLeft(label) if dirname: components.append(dirname) else: components.append(label) break return components # Generic methods that deal with extensions. def GetExtension(self, id): """Return the extension object named 'id'. 'id' -- The label for the extension. returns -- The instance of 'Extension' with the indicated name, or 'None' if there is no such entity. Database classes should override this method. For backwards compatibility, this base class implements this generic method in terms of the special-purpose methods 'GetTest()' and 'GetResource()'. Only if _is_generic_database is True are these implemented in terms of 'GetExtension()'.""" for kind in (Database.TEST, Database.RESOURCE): try: return self.GetItem(kind, id).GetItem() except NoSuchItemError: pass try: return self.GetSuite(id) except NoSuchSuiteError: pass return None def GetExtensions(self, directory, scan_subdirs): """Return the extensions in 'directory'. 'directory' -- The name of a directory. 'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned. returns -- A dictionary mapping labels to 'Extension' instances. The dictionary contains all extensions in 'directory', and, if 'scan_subdirs' is true, its subdirectories.""" extensions = {} for kind in self.ITEM_KINDS: ids = self.GetIds(kind, directory, scan_subdirs) for id in ids: extensions[id] = self.GetExtension(id) return extensions def RemoveExtension(self, id, kind): """Remove the extension 'id' from the database. 'id' -- A label for the 'Extension' instance stored in the database. 'kind' -- The kind of 'Extension' stored with the given 'id'.""" raise NotImplementedError def WriteExtension(self, id, extension): """Store 'extension' in the database, using the name 'id'. 'id' -- A label for the 'extension'. 'extension' -- An instance of 'Extension'. The 'extension' is stored in the database. If there is a previous item in the database with the same id, it is removed and replaced with 'extension'. Some databases may not be able to store all 'Extension' instances; those database must throw an exception when an attempt is made to store such an 'extension'.""" raise NotImplementedError # Methods that deal with tests. def GetTest(self, test_id): """Return the 'TestDescriptor' for the test named 'test_id'. 'test_id' -- A label naming the test. returns -- A 'TestDescriptor' corresponding to 'test_id'. raises -- 'NoSuchTestError' if there is no test in the database named 'test_id'.""" if self._is_generic_database: test = self.GetExtension(test_id) if isinstance(test, Test): return TestDescriptor(self, test_id, test=test) raise NoSuchTestError(test_id) def HasTest(self, test_id): """Check whether or not the database has a test named 'test_id'. 'test_id' -- A label naming the test. returns -- True if and only if the database contains a test named 'test_id'. If this function returns true, 'GetTest' will usually succeed. However, they may be circumstances where 'HasTest' returns true and 'GetTest' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasTest' is called and the time that 'GetTest' is called. Derived classes may override this method.""" try: self.GetTest(test_id) except NoSuchTestError: return 0 else: return 1 def GetTestIds(self, directory="", scan_subdirs=1): """Return all test IDs that begin with 'directory'. 'directory' -- A label indicating the directory in which to begin the search. 'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned. 'returns' -- A list of all tests located within 'directory', as absolute labels.""" return self.GetIds(self.TEST, directory, scan_subdirs) # Methods that deal with suites. def GetSuite(self, suite_id): """Return the 'Suite' for the suite named 'suite_id'. 'suite_id' -- A label naming the suite. returns -- An instance of 'Suite' (or a derived class of 'Suite') corresponding to 'suite_id'. raises -- 'NoSuchSuiteError' if there is no test in the database named 'test_id'. All databases must have an implicit suite called '' that contains all tests in the database. More generally, for each directory in the database, there must be a corresponding suite that contains all tests in that directory and its subdirectories.""" if suite_id == "": return DirectorySuite(self, "") if self._is_generic_database: suite = self.GetExtension(suite_id) if isinstance(suite, Suite): return suite raise NoSuchSuiteError(suite_id) def HasSuite(self, suite_id): """Check whether or not the database has a suite named 'suite_id'. 'suite_id' -- A label naming the suite. returns -- True if and only if the database contains a suite named 'suite_id'. If this function returns true, 'GetSuite' will usually succeed. However, they may be circumstances where 'HasSuite' returns true and 'GetSuite' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasSuite' is called and the time that 'GetSuite' is called. All databases must have an implicit suite called "" that contains all tests in the database. More generally, for each directory in the database, there must be a corresponding suite that contains all tests in that directory and its subdirectories. Derived classes may override this method.""" try: self.GetSuite(suite_id) except NoSuchSuiteError: return 0 else: return 1 def GetSuiteIds(self, directory="", scan_subdirs=1): """Return all suite IDs that begin with 'directory'. 'directory' -- A label indicating the directory in which to begin the search. 'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned. 'returns' -- A list of all suites located within 'directory', as absolute labels.""" return self.GetIds(self.SUITE, directory, scan_subdirs) # Methods that deal with resources. def GetResource(self, resource_id): """Return the 'ResourceDescriptor' for the resource 'resouce_id'. 'resource_id' -- A label naming the resource. returns -- A 'ResourceDescriptor' corresponding to 'resource_id'. raises -- 'NoSuchResourceError' if there is no resource in the database named 'resource_id'.""" if self._is_generic_database: resource = self.GetExtension(resource_id) if isinstance(resource, Resource): return ResourceDescriptor(self, resource_id, resource = resource) raise NoSuchResourceError(resource_id) def HasResource(self, resource_id): """Check whether or not the database has a resource named 'resource_id'. 'resource_id' -- A label naming the resource. returns -- True if and only if the database contains a resource named 'resource_id'. If this function returns true, 'GetResource' will usually succeed. However, they may be circumstances where 'HasResource' returns true and 'GetResource' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasResource' is called and the time that 'GetResource' is called. Derived classes may override this method.""" try: self.GetResource(resource_id) except NoSuchResourceError: return 0 else: return 1 def GetResourceIds(self, directory="", scan_subdirs=1): """Return all resource IDs that begin with 'directory'. 'directory' -- A label indicating the directory in which to begin the search. 'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned. 'returns' -- A list of all resources located within 'directory', as absolute labels.""" return self.GetIds(self.RESOURCE, directory, scan_subdirs) # Miscellaneous methods. def GetIds(self, kind, directory = "", scan_subdirs = 1): """Return all IDs of the indicated 'kind' that begin with 'directory'. 'kind' -- One of the 'ITEM_KINDS'. 'directory' -- A label indicating the directory in which to begin the search. 'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned. returns -- A list of all items of the indicated 'kind' located within 'directory', as absolute labels. Derived classes may override this method.""" if self._is_generic_database: extensions = self.GetExtensions(directory, scan_subdirs) extensions = filter(lambda e: e.kind == kind, extensions.values()) return map(lambda e: e.GetId(), extensions) return [] def GetItem(self, kind, item_id): """Return the item of the indicated 'kind' with indicated 'item_id'. 'kind' -- One of the 'ITEM_KINDS'. 'item_id' -- The name of the item. returns -- If 'kind' is 'Database.TEST' or 'Database.RESOURCE', returns a test descriptor or resource descriptor, respectively. If 'kind' is 'Database.SUITE', returns a 'Suite'. Derived classes may override this method.""" return { Database.TEST : self.GetTest, Database.RESOURCE : self.GetResource, Database.SUITE : self.GetSuite } [kind] (item_id) def GetSubdirectories(self, directory): """Return the immediate subdirectories of 'directory'. 'directory' -- A label indicating a directory in the database. returns -- A sequence of (relative) labels indictating the immediate subdirectories of 'directory'. For example, if "a.b" and "a.c" are directories in the database, this method will return "b" and "c" given "a" as 'directory'. Derived classes may override this method.""" return [] def GetPath(self): """Return the directory containing the database. returns -- A string containing the absolute path to the directory containing the database. Derived classes must not override this method.""" return self.__path def GetConfigurationDirectory(self): """Return the directory containing configuration information. returns -- The directory containing configuration information for the database. Derived classes must not override this method.""" return get_configuration_directory(self.GetPath()) def GetAttachmentStore(self): """Returns the 'AttachmentStore' associated with the database. returns -- The 'AttachmentStore' containing the attachments associated with tests and resources in this database. Derived classes may override this method.""" return None def GetClassPaths(self): """Return directories to search for test and resource classes. returns -- A sequence of strings. Each string is a directory that should be searched to locate test and resource classes. The directories will be searched in the order they appear. QMTest will search other directories (like those in the 'QMTEST_CLASS_PATH' environment variable) in addition to these directories. For a given database, this method should always return the same value; callers are permitted to cache the value returned. Derived classes may override this method. The sequence returned by the derived class need not be a superset of the value returned by the default implementation (but probably should be).""" return [] def GetTestClassNames(self): """Return the kinds of tests that the database can store. returns -- A sequence of strings. Each string names a class, including the containing module. Only classes of these types can be stored in the database. Derived classes may override this method. The default implementation allows all available test classes, but the derived class may allow only a subset.""" return get_extension_class_names('test', self) def GetResourceClassNames(self): """Return the kinds of resources that the database can store. returns -- A sequence of strings. Each string names a class, including the containing module. Only resources of these types can be stored in the database. Derived classes may override this method. The default implementation allows all available resource classes, but the derived class may allow only a subset.""" return get_extension_class_names('resource', self) def ExpandIds(self, ids): """Expand test and suite IDs into test IDs. 'ids' -- A sequence of IDs of tests and suites, which may be mixed together. returns -- A pair 'test_ids, suite_ids'. 'test_ids' is a sequence of test IDs including all test IDs mentioned in 'ids' plus all test IDs obtained from recursively expanding suites included in 'ids'. 'suite_ids' is the set of IDs of suites included directly and indirectly in 'ids'. raises -- 'ValueError' if an element in 'id' is neither a test or suite ID. The exception argument is the erroneous element.""" # We'll collect test and suite IDs in maps, to make duplicate # checks efficient. test_ids = {} suite_ids = {} for id in ids: # Skip this ID if we've already seen it. if suite_ids.has_key(id) or test_ids.has_key(id): continue # Is this a suite ID? if self.HasSuite(id): suite_ids[id] = None # Yes. Load the suite. suite = self.GetSuite(id) # Determine all the tests and suites contained directly and # indirectly in this suite. suite_test_ids, sub_suite_ids = suite.GetAllTestAndSuiteIds() # Add them. for test_id in suite_test_ids: test_ids[test_id] = None for suite_id in sub_suite_ids: suite_ids[suite_id] = None # Or is this a test ID? elif self.HasTest(id): # Yes. Add it. test_ids[id] = None else: # It doesn't look like a test or suite ID. raise ValueError, id # Convert the maps to sequences. return test_ids.keys(), suite_ids.keys() def IsModifiable(self): """Returns true iff this database is modifiable. returns -- True iff this database is modifiable. If the database is modifiable, it supports operatings like 'Write' that make changes to the structure of the databaes itself. Otherwise, the contents of the database may be viewed, but not modified.""" return self.modifiable == "true" ######################################################################## # Functions ######################################################################## def get_configuration_directory(path): """Return the configuration directory for the 'Database' rooted at 'path'. 'path' -- The path to the test database. returns -- The path to the configuration directory.""" return os.path.join(path, "QMTest") def get_configuration_file(path): """Return the configuration file for the 'Database' rooted at 'path'. 'path' -- The path to the test database. returns -- The path to the configuration file.""" return os.path.join(get_configuration_directory(path), "configuration") def is_database(db_path): """Returns true if 'db_path' looks like a test database.""" # A test database is a directory. if not os.path.isdir(db_path): return 0 # A test database contains a configuration file. if not os.path.isfile(get_configuration_file(db_path)): return 0 # It probably is OK. return 1 def load_database(db_path): """Load the database from 'db_path'. 'db_path' -- The path to the directory containing the database. returns -- The new 'Database'.""" # Make sure it is a directory. if not is_database(db_path): raise QMException, \ qm.error("not test database", path=db_path) # Load the file. config_path = get_configuration_file(db_path) document = qm.xmlutil.load_xml_file(config_path) # Parse it. database_class, arguments \ = (qm.extension.parse_dom_element (document.documentElement, lambda n: qm.test.base.get_extension_class(n, "database", None, db_path))) # For backwards compatibility with QM 1.1.x, we look for "attribute" # elements. for node in document.documentElement.getElementsByTagName("attribute"): name = node.getAttribute("name") # These elements were only allowed to contain strings as # values. value = qm.xmlutil.get_dom_text(node) # Python does not allow keyword arguments to have Unicode # values, so we convert the name to an ordinary string. arguments[str(name)] = value return database_class(db_path, arguments) ######################################################################## # Functions ######################################################################## def set_path(path): """Set the database path to be used when the database is loaded. 'path' -- A string containing the path to the database.""" global __the_db_path __the_db_path = path def get_database(): """Returns the global Database object. returns -- The 'Database' object that corresponds to the currently executing process. It may be None.""" global __the_database if not __the_database: __the_database = load_database(__the_db_path) return __the_database ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/result.py0000664000076400007640000003506111107032225015651 0ustar stefanstefan######################################################################## # # File: result.py # Author: Mark Mitchell # Date: 2001-10-10 # # Contents: # QMTest Result class. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm from qm.test.context import ContextException import sys, os import types import cgi ######################################################################## # Classes ######################################################################## class Result: """A 'Result' describes the outcome of a test. A 'Result' contains two pieces of data: an outcome and a set of annotations. The outcome indicates whether the test passed or failed. More specifically, the outcome may be one of the following constants: 'Result.PASS' -- The test passed. 'Result.FAIL' -- The test failed. 'Result.ERROR' -- Something went wrong in the process of trying to execute the test. For example, if the Python code implementing the 'Run' method in the test class raised an exception, the outcome would be 'Result.ERROR'. 'Result.UNTESTED' -- QMTest did not even try to run the test. For example, if a prerequiste was not satisfied, then this outcome will be used.' The annotations are a dictionary, mapping strings to strings. The indices should be of the form 'class.name' where 'class' is the name of the test class that created the annotation. Any annotations created by QMTest, as opposed to the test class, will have indices of the form 'qmtest.name'. The annotation values are HTML. When displayed in the GUI, the HTML is inserted directly into the result page; when the command-line interface is used the HTML is converted to plain text. Currently, QMTest recognizes the following built-in annotations: 'Result.CAUSE' -- For results whose outcome is not 'FAIL', this annotation gives a brief description of why the test failed. The preferred form of this message is a phrase like "Incorrect output." or "Exception thrown." The message should begin with a capital letter and end with a period. Most results formatters will display this information prominently. 'Result.EXCEPTION' -- If an exeption was thrown during the test execution, a brief description of the exception. 'Result.TARGET' -- This annotation indicates on which target the test was executed. 'Result.TRACEBACK' -- If an exeption was thrown during the test execution, a representation of the traceback indicating where the exception was thrown. A 'Result' object has methods that allow it to act as a dictionary from annotation names to annotation values. You can directly add an annotation to a 'Result' by writing code of the form 'result[CAUSE] = "Exception thrown."'. A 'Result' object is also used to describe the outcome of executing either setup or cleanup phase of a 'Resource'.""" # Constants for result kinds. RESOURCE_SETUP = "resource_setup" RESOURCE_CLEANUP = "resource_cleanup" TEST = "test" # Constants for outcomes. FAIL = "FAIL" ERROR = "ERROR" UNTESTED = "UNTESTED" PASS = "PASS" # Constants for predefined annotations. CAUSE = "qmtest.cause" EXCEPTION = "qmtest.exception" RESOURCE = "qmtest.resource" TARGET = "qmtest.target" TRACEBACK = "qmtest.traceback" START_TIME = "qmtest.start_time" END_TIME = "qmtest.end_time" # Other class variables. kinds = [ RESOURCE_SETUP, RESOURCE_CLEANUP, TEST ] """A list of the possible kinds.""" outcomes = [ ERROR, FAIL, UNTESTED, PASS ] """A list of the possible outcomes. The order of the 'outcomes' is significant; they are ordered from most interesting to least interesting from the point of view of someone browsing results.""" def __init__(self, kind, id, outcome=PASS, annotations={}): """Construct a new 'Result'. 'kind' -- The kind of result. The value must be one of the 'Result.kinds'. 'id' -- The label for the test or resource to which this result corresponds. 'outcome' -- The outcome associated with the test. The value must be one of the 'Result.outcomes'. 'annotations' -- The annotations associated with the test.""" assert kind in Result.kinds assert outcome in Result.outcomes self.__kind = kind self.__id = id self.__outcome = outcome self.__annotations = annotations.copy() def __getstate__(self): """Return a representation of this result for pickling. By using an explicit tuple representation of 'Result's when storing them in a pickle file, we decouple our storage format from internal implementation details (e.g., the names of private variables).""" # A tuple containing the data needed to reconstruct a 'Result'. # No part of this structure should ever be a user-defined type, # because that will introduce interdependencies that we want to # avoid. return (self.__kind, self.__id, self.__outcome, self.__annotations) def __setstate__(self, pickled_state): """Construct a 'Result' from its pickled form.""" if isinstance(pickled_state, dict): # Old style pickle, from before we defined '__getstate__'. # (Notionally, this is version "0".) The state is a # dictionary containing the variables we used to have. self.__kind = pickled_state["_Result__kind"] self.__id = pickled_state["_Result__id"] self.__outcome = pickled_state["_Result__outcome"] self.__annotations = pickled_state["_Result__annotations"] # Also has a key "_Result__context" containing a (probably # invalid) context object, but we discard it. else: assert isinstance(pickled_state, tuple) \ and len(pickled_state) == 4 # New style pickle, from after we defined '__getstate__'. # (Notionally, this is version "1".) The state is a tuple # containing the values of the variables we care about. (self.__kind, self.__id, self.__outcome, self.__annotations) = pickled_state def GetKind(self): """Return the kind of result this is. returns -- The kind of entity (one of the 'kinds') to which this result corresponds.""" return self.__kind def GetOutcome(self): """Return the outcome associated with the test. returns -- The outcome associated with the test. This value will be one of the 'Result.outcomes'.""" return self.__outcome def SetOutcome(self, outcome, cause = None, annotations = {}): """Set the outcome associated with the test. 'outcome' -- One of the 'Result.outcomes'. 'cause' -- If not 'None', this value becomes the value of the 'Result.CAUSE' annotation. 'annotations' -- The annotations are added to the current set of annotations.""" assert outcome in Result.outcomes self.__outcome = outcome if cause: self.SetCause(cause) self.Annotate(annotations) def Annotate(self, annotations): """Add 'annotations' to the current set of annotations.""" self.__annotations.update(annotations) def Fail(self, cause = None, annotations = {}): """Mark the test as failing. 'cause' -- If not 'None', this value becomes the value of the 'Result.CAUSE' annotation. 'annotations' -- The annotations are added to the current set of annotations.""" self.SetOutcome(Result.FAIL, cause, annotations) def GetId(self): """Return the label for the test or resource. returns -- A label indicating indicating to which test or resource this result corresponds.""" return self.__id def GetCause(self): """Return the cause of failure, if the test failed. returns -- If the test failed, return the cause of the failure, if available.""" if self.has_key(Result.CAUSE): return self[Result.CAUSE] else: return "" def SetCause(self, cause): """Set the cause of failure. 'cause' -- A string indicating the cause of failure. Like all annotations, 'cause' will be interested as HTML.""" self[Result.CAUSE] = cause def Quote(self, string): """Return a version of string suitable for an annotation value. Performs appropriate quoting for a string that should be taken verbatim; this includes HTML entity escaping, and addition of
 tags.

        'string' -- The verbatim string to be quoted.

        returns -- The quoted string."""

        return "
%s
" % cgi.escape(string) def NoteException(self, exc_info = None, cause = None, outcome = ERROR): """Note that an exception occurred during execution. 'exc_info' -- A triple, in the same form as that returned from 'sys.exc_info'. If 'None', the value of 'sys.exc_info()' is used instead. 'cause' -- The value of the 'Result.CAUSE' annotation. If 'None', a default message is used. 'outcome' -- The outcome of the test, now that the exception has occurred. A test class can call this method if an exception occurs while the test is being run.""" if not exc_info: exc_info = sys.exc_info() exception_type = exc_info[0] # If no cause was specified, use an appropriate message. if not cause: if exception_type is ContextException: cause = str(exc_info[1]) else: cause = "An exception occurred." # For a 'ContextException', indicate which context variable # was invalid. if exception_type is ContextException: self["qmtest.context_variable"] = exc_info[1].key self.SetOutcome(outcome, cause) self[Result.EXCEPTION] \ = self.Quote("%s: %s" % exc_info[:2]) self[Result.TRACEBACK] \ = self.Quote(qm.format_traceback(exc_info)) def CheckExitStatus(self, prefix, desc, status, non_zero_exit_ok = 0): """Check the exit status from a command. 'prefix' -- The prefix that should be used when creating result annotations. 'desc' -- A description of the executing program. 'status' -- The exit status, as returned by 'waitpid'. 'non_zero_exit_ok' -- True if a non-zero exit code is not considered failure. returns -- False if the test failed, true otherwise.""" if sys.platform == "win32" or os.WIFEXITED(status): # Obtain the exit code. if sys.platform == "win32": exit_code = status else: exit_code = os.WEXITSTATUS(status) # If the exit code is non-zero, the test fails. if exit_code != 0 and not non_zero_exit_ok: self.Fail("%s failed with exit code %d." % (desc, exit_code)) # Record the exit code in the result. self[prefix + "exit_code"] = str(exit_code) return False elif os.WIFSIGNALED(status): # Obtain the signal number. signal = os.WTERMSIG(status) # If the program gets a fatal signal, the test fails . self.Fail("%s received fatal signal %d." % (desc, signal)) self[prefix + "signal"] = str(signal) return False else: # A process should only be able to stop by exiting, or # by being terminated with a signal. assert None return True def MakeDomNode(self, document): """Generate a DOM element node for this result. Note that the context is not represented in the DOM node. 'document' -- The containing DOM document. returns -- The element created.""" # The node is a result element. element = document.createElement("result") element.setAttribute("id", self.GetId()) element.setAttribute("kind", self.GetKind()) element.setAttribute("outcome", str(self.GetOutcome())) # Add an annotation element for each annotation. keys = self.keys() keys.sort() for key in keys: value = self[key] annotation_element = document.createElement("annotation") # The annotation name is an attribute. annotation_element.setAttribute("name", str(key)) # The annotation value is contained in a text node. The # data is enclosed in quotes for robustness if the # document is pretty-printed. node = document.createTextNode('"' + str(value) + '"') annotation_element.appendChild(node) # Add the annotation element to the result node. element.appendChild(annotation_element) return element # These methods allow 'Result' to act like a dictionary of # annotations. def __getitem__(self, key): assert type(key) in types.StringTypes return self.__annotations[key] def __setitem__(self, key, value): assert type(key) in types.StringTypes assert type(value) in types.StringTypes self.__annotations[key] = value def __delitem__(self, key): assert type(key) in types.StringTypes del self.__annotations[key] def get(self, key, default=None): assert type(key) in types.StringTypes return self.__annotations.get(key, default) def has_key(self, key): assert type(key) in types.StringTypes return self.__annotations.has_key(key) def keys(self): return self.__annotations.keys() def items(self): return self.__annotations.items() ######################################################################## # Variables ######################################################################## __all__ = ["Result"] qmtest-2.4.1/qm/test/file_result_reader.py0000664000076400007640000000564611107032225020200 0ustar stefanstefan######################################################################## # # File: file_result_reader.py # Author: Nathaniel Smith # Date: 2003-06-23 # # Contents: # FileResultReader # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.fields import TextField, PythonField from qm.common import QMException from qm.test.result_reader import ResultReader import sys ######################################################################## # Classes ######################################################################## class FileResultReader(ResultReader): """A 'FileResultReader' gets its input from a file. A 'FileResultReader' is an abstract base class for other result reader classes that read results from a single file. The file from which results should be read can be specified using either the 'filename' argument or the 'file' argument. The latter is for use by QMTest internally.""" class InvalidFile(QMException): """An 'InvalidFile' exception indicates an incorrect file format. If the constructor for a 'FileResultStream' detects an invalid file, it must raise an instance of this exception.""" pass arguments = [ TextField( name = "filename", title = "File Name", description = """The name of the file. All results will be read from the file indicated. If no filename is specified, or the filename specified is "-", the standard input will be used.""", verbatim = "true", default_value = ""), PythonField( name = "file"), ] _is_binary_file = 0 """If true, results are stored in a binary format. This flag can be overridden by derived classes.""" def __init__(self, arguments = None, **args): """Construct a new 'FileResultReader'. 'arguments' -- As for 'ResultReader'. If the file provided is not in the input format expected by this result reader, the derived class '__init__' function must raise an 'InvalidStream' exception.""" super(FileResultReader, self).__init__(arguments, **args) if not self.file: if self.filename and self.filename != "-": if self._is_binary_file: mode = "rb" else: mode = "r" self.file = open(self.filename, mode, 0) else: self.file = sys.stdin ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/run_database.py0000664000076400007640000001310711107032225016760 0ustar stefanstefan######################################################################## # # File: run_database.py # Author: Mark Mitchell # Date: 2005-08-08 # # Contents: # QMTest RunDatabase class. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.extension import Extension from qm.test.result import Result from qm.common import parse_time_iso ######################################################################## # Classes ######################################################################## class RunDatabase(Extension): """A 'RunDatabase' stores 'TestRun's. A 'RunDatabase' provides a mechanism for selecting 'TestRun's that meet particular criteria.""" def GetAllRuns(self): """Return all the 'TestRun's in the database. returns -- A sequence consisting of all of the 'TestRun's in the database.""" raise NotImplementedError def GetRuns(self, predicate): """Return the set of 'TestRun's satisfying 'predicate' 'predicate' -- A callable that can be passed one 'TestRun' argument. returns -- A sequence of 'TestRun's consisting only of those 'TestRun's in the database for which 'predicate' returns a true value.""" return filter(self.GetAllRuns(), predicate) def GetAnnotations(self, key): """Return the set of annotations for 'key' from all test runs. 'key' -- A string used to look up the annotations. returns -- A set of (distinct) annotations for 'key' from all test runs.""" # We can't use sets since we want to remain python 2.2 compatible. annotations = [] for r in self.GetAllRuns(): value = r.GetAnnotation(key) if value not in annotations: annotations.append(value) return annotations def GetTimeframe(self, time_key, is_iso_time = True): """Return a pair of min / max values found for the given time_key across all test runs. 'time_key' -- Annotation key referring to a string convertible to either iso-formatted time or floating point number. returns -- minimum, maximum.""" minimum = None maximum = None for r in self.GetAllRuns(): time_string = r.GetAnnotation(time_key) if not time_string: continue if is_iso_time: time = parse_time_iso(time_string) else: time = float(time_string) if not minimum or minimum > time: minimum = time if not maximum or maximum < time: # Make sure the largest value is still inside the interval. maximum = time + 0.1 return minimum, maximum def GetRunInTimeframe(self, key, value, time_key, minimum, maximum, is_iso_time = True): """Return a test run id matching the key and timeframe.""" for i in range(len(self.GetAllRuns())): r = self.GetAllRuns()[i] if r.GetAnnotation(key) != value: continue time_string = r.GetAnnotation(time_key) if not time_string: continue if is_iso_time: time = parse_time_iso(time_string) else: time = float(time_string) if time >= minimum and time < maximum: return i # No match. return None def GetRunsByAnnotations(self, annotation_filter): """Return the 'TestRun's matching 'annotation_filter'. 'annotation_filter' -- A dictionary mapping annotation keys (strings) to values (either strings or callables). returns -- A sequence of 'TestRun's consisting only of those 'TestRun's in the database that match the 'annotation_filter'. A 'TestRun' matches the 'annotation_filter' if it matches each of the key-value pairs in the filter. If the value in such a pair is a string, then the annotation in the 'TestRun' must exactly match the value. If the value is a callable, rather than a string, then when passed the value from the 'TestRun', the predicate must return a true value.""" def predicate(run): for key, pattern in annotation_filter.iteritems(): value = run.GetAnnotation(key) if callable(pattern): if not pattern(value): return False elif value != pattern: return False return True return self.GetRuns(predicate) def GetOutcomes(self, id, kind = Result.TEST): """Return an outcome dictionary for the indicated test. 'id' -- The name of a test, suite, or resource item. 'kind' -- The kind of the item to retrieve the outcome for. returns -- A dictionary indicating the number of outcomes per category.""" outcomes = {Result.PASS: 0, Result.FAIL: 0, Result.ERROR: 0, Result.UNTESTED: 0} for r in self.GetAllRuns(): result = r.GetResult(id, kind) if result: outcomes[result.GetOutcome()] += 1 else: outcomes[Result.UNTESTED] += 1 return outcomes qmtest-2.4.1/qm/test/base.py0000664000076400007640000004332511107032225015247 0ustar stefanstefan######################################################################## # # File: base.py # Author: Alex Samuel # Date: 2001-03-08 # # Contents: # Base interfaces and classes. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import cPickle import cStringIO import os import qm import qm.attachment from qm.common import * from qm.test.file_result_reader import FileResultReader from qm.test.expectation_database import ExpectationDatabase import qm.platform import qm.structured_text from qm.test.context import * from qm.test.result import * import qm.xmlutil import string import sys import tempfile import types ######################################################################## # Exceptions ######################################################################## class CouldNotLoadExtensionError(QMException): """An exception indicating that an extension class could not be loaded.""" def __init__(self, class_name, exc_info): """Construct a new 'CouldNotLoadExtensionError'. 'class_name' -- The name of the class. 'exc_info' -- An exception tuple, as returned by 'sys.exc_info'.""" self.exc_info = exc_info message = qm.common.format_exception(exc_info) message += "\n" + qm.error("could not load extension class", class_name = class_name) QMException.__init__(self, message) ######################################################################## # Functions ######################################################################## def get_extension_directories(kind, database, database_path = None): """Return the directories to search for QMTest extensions. 'kind' -- A string giving kind of extension for which we are looking. This must be of the elements of 'extension_kinds'. 'database' -- The 'Database' with which the extension class will be used, or 'None'. 'database_path' -- The path from which the database will be loaded. If 'None', 'database.GetPath()' is used. returns -- A sequence of strings. Each string is the path to a directory that should be searched for QMTest extensions. The directories must be searched in order; the first directory containing the desired module is the one from which the module is loaded. The directories that are returned are, in order: 1. Those directories present in the 'QMTEST_CLASS_PATH' environment variable. 2. Those directories specified by the 'GetClassPaths' method on the test database -- unless 'kind' is 'database'. 3. The directory specified by config.extension_path. 4. The directories containing classes that come with QMTest. By placing the 'QMTEST_CLASS_PATH' directories first, users can override test classes with standard names.""" global extension_kinds # The kind should be one of the extension_kinds. assert kind in extension_kinds # Start with the directories that the user has specified in the # QMTEST_CLASS_PATH environment variable. if os.environ.has_key('QMTEST_CLASS_PATH'): dirs = string.split(os.environ['QMTEST_CLASS_PATH'], os.pathsep) else: dirs = [] # Search directories specified by the database. if database: dirs = dirs + database.GetClassPaths() # Search the database configuration directory. if database: dirs.append(database.GetConfigurationDirectory()) elif database_path: dirs.append(qm.test.database.get_configuration_directory (database_path)) # Search qmtest's own site-extensions directory. dirs.append(os.path.join(qm.prefix, qm.extension_path)) dirs.append(qm.common.get_lib_directory('test', 'classes')) return dirs def get_extension_class_names_in_directory(directory): """Return the names of QMTest extension classes in 'directory'. 'directory' -- A string giving the path to a directory in the file system. returns -- A dictionary mapping the strings in 'extension_kinds' to sequences of strings. Each element in the sequence names an extension class, using the form 'module.class'""" global extension_kinds # Assume that there are no extension classes in this directory. extensions = {} for kind in extension_kinds: extensions[kind] = [] # Look for a file named 'classes.qmc' in this directory. file = os.path.join(directory, 'classes.qmc') # If the file does not exist, there are no extension classes in # this directory. if not os.path.isfile(file): return extensions try: # Load the file. document = qm.xmlutil.load_xml_file(file) # Get the root node in the document. root = document.documentElement # Get the sequence of elements corresponding to each of the # classes listed in the directory. classes = root.getElementsByTagName("class") # Go through each of the classes to see what kind it is. for c in classes: kind = c.getAttribute('kind') # Skip extensions we do not understand. Perhaps they # are for some other QM tool. if kind not in extension_kinds: continue if c.hasAttribute("name"): name = c.getAttribute("name") else: # Before QMTest 2.1, the class name was contained in # the class element, rather than being an attribute. name = qm.xmlutil.get_dom_text(c) # Strip whitespace. name = name.strip() extensions[kind].append(name) except: raise return extensions def get_extension_class_names(kind, database, database_path = None): """Return the names of extension classes. 'kind' -- The kind of extension class. This value must be one of the 'extension_kinds'. 'database' -- The 'Database' with which the extension class will be used, or 'None' if 'kind' is 'database'. 'database_path' -- The path from which the database will be loaded. If 'None', 'database.GetPath()' is used. returns -- A sequence of strings giving the names of the extension classes with the indicated 'kind', in the form 'module.class'.""" dirs = get_extension_directories(kind, database, database_path) names = [] for d in dirs: names.extend(get_extension_class_names_in_directory(d)[kind]) return names def get_extension_class_from_directory(class_name, kind, directory, path): """Load an extension class from 'directory'. 'class_name' -- The name of the extension class, in the form 'module.class'. 'kind' -- The kind of class to load. This value must be one of the 'extension_kinds'. 'directory' -- The directory from which to load the class. 'path' -- The directories to search for modules imported by the new module. returns -- The class loaded.""" global __class_caches global __extension_bases # If this class is already in the cache, we can just return it. cache = __class_caches[kind] if cache.has_key(class_name): return cache[class_name] # Load the class. try: klass = qm.common.load_class(class_name, [directory], path + sys.path) except: raise CouldNotLoadExtensionError(class_name, sys.exc_info()) # Make sure the class is derived from the appropriate base class. if not issubclass(klass, __extension_bases[kind]): raise QMException, \ qm.error("extension class not subclass", kind = kind, class_name = class_name, base_name = __extension_bases[kind].__name__) # Cache it. cache[class_name] = klass return klass def get_extension_class(class_name, kind, database, database_path = None): """Return the extension class named 'class_name'. 'class_name' -- The name of the class, in the form 'module.class'. 'kind' -- The kind of class to load. This value must be one of the 'extension_kinds'. 'database' -- The 'Database' with which the extension class will be used, or 'None' if 'kind' is 'database'. 'database_path' -- The path from which the database will be loaded. If 'None', 'database.GetPath()' is used. returns -- The class object with the indicated 'class_name'.""" global __class_caches # If this class is already in the cache, we can just return it. cache = __class_caches[kind] if cache.has_key(class_name): return cache[class_name] # For backwards compatibility with QM 1.1.x, we accept # "xmldb.Database" and "qm.test.xmldb.Database", even though those # to do not name actual database classes any more. if kind == "database" and class_name in ("xmldb.Database", "qm.test.xmldb.Database"): class_name = "xml_database.XMLDatabase" # Look for the class in each of the extension directories. directories = get_extension_directories(kind, database, database_path) directory = None for d in directories: if class_name in get_extension_class_names_in_directory(d)[kind]: directory = d break # If the class could not be found, issue an error. if not directory: raise QMException, qm.error("extension class not found", klass=class_name) # Load the class. return get_extension_class_from_directory(class_name, kind, directory, directories) def get_test_class(class_name, database): """Return the test class named 'class_name'. 'class_name' -- The name of the test class, in the form 'module.class'. returns -- The test class object with the indicated 'class_name'.""" return get_extension_class(class_name, 'test', database) def get_resource_class(class_name, database): """Return the resource class named 'class_name'. 'class_name' -- The name of the resource class, in the form 'module.class'. returns -- The resource class object with the indicated 'class_name'.""" return get_extension_class(class_name, 'resource', database) def get_extension_classes(kind, database = None): """Return the extension classes for the given 'kind'. 'kind' -- The kind of extensions being sought. The value must be one of the 'extension_kinds'. 'database' -- If not 'None', the test 'Database' in use. returns -- A list of the available extension classes of the indicated 'kind'.""" classes = [] directories = get_extension_directories(kind, database) for d in directories: names = get_extension_class_names_in_directory(d)[kind] d_classes = [get_extension_class_from_directory(n, kind, d, directories) for n in names] classes.extend(d_classes) return classes def load_results(file, database): """Read test results from a file. 'file' -- The filename or file object from which to read the results. If 'file' is not a string, then it is must be a seekable file object, and this function will look for a 'FileResultReader' that accepts the file. If 'file' is a string, then it is treated as either a filename or as an extension descriptor. 'database' -- The current database. returns -- A 'ResultReader' object, or raises an exception if no appropriate reader is available.""" f = None if isinstance(file, types.StringTypes): if os.path.exists(file): f = open(file, "rb") else: f = file if f: # Find the first FileResultStream that will accept this file. for c in get_extension_classes("result_reader", database): if issubclass(c, FileResultReader): try: return c({"file" : f}) except FileResultReader.InvalidFile: # Go back to the beginning of the file. f.seek(0) if not isinstance(file, types.StringTypes): raise FileResultReader.InvalidFile, \ "not a valid results file" if database: extension_loader = database.GetExtension else: extension_loader = None class_loader = lambda n: get_extension_class(n, "result_reader", database) cl, args = qm.extension.parse_descriptor(file, class_loader, extension_loader) return cl(args) def load_expectations(file, database, annotations = None): """Read expectations from a file. 'file' -- The filename or file object from which to read the expectations. If 'file' is not a string, then it is must be a seekable file object, and this function will look for an 'ExpectationDatabase' that accepts the file. If 'file' is a string, then it is treated as either a filename or as an extension descriptor. 'database' -- The current database. 'annotations' -- Annotations for the current test run. returns -- An 'ExpectationDatabase' object, or raises an exception if no appropriate reader is available.""" if not file: return ExpectationDatabase() f = None if isinstance(file, (str, unicode)): if os.path.exists(file): f = open(file, "rb") else: f = file if f: return PreviousTestRun(test_database = database, results_file = f) if not isinstance(file, (str, unicode)): raise QMException, "not a valid expectation database" if database: extension_loader = database.GetExtension else: extension_loader = None class_loader = lambda n: get_extension_class(n, "expectation_database", database) cl, args = qm.extension.parse_descriptor(file, class_loader, extension_loader) args['test_database'] = database args['testrun_parameters'] = annotations or {} return cl(**args) def load_outcomes(file, database): """Load test outcomes from a file. 'file' -- The file object from which to read the results. See 'load_results' for details. 'database' -- The current database. returns -- A map from test IDs to outcomes.""" results = load_results(file, database) outcomes = {} for r in results: # Keep test outcomes only. if r.GetKind() == Result.TEST: outcomes[r.GetId()] = r.GetOutcome() return outcomes def _result_from_dom(node): """Extract a result from a DOM node. 'node' -- A DOM node corresponding to a "result" element. returns -- A 'Result' object. The context for the result is 'None', since context is not represented in a result DOM node.""" assert node.tagName == "result" # Extract the outcome. outcome = qm.xmlutil.get_child_text(node, "outcome") # Extract the test ID. test_id = node.getAttribute("id") kind = node.getAttribute("kind") # Build a Result. result = Result(kind, test_id, outcome) # Extract properties, one for each property element. for property_node in node.getElementsByTagName("property"): # The name is stored in an attribute. name = property_node.getAttribute("name") # The value is stored in the child text node. value = qm.xmlutil.get_dom_text(property_node) # Store it. result[name] = value return result ######################################################################## # variables ######################################################################## import qm.test.database import qm.label import qm.host import qm.test.resource import qm.test.result_reader import qm.test.result_stream import qm.test.run_database import qm.test.expectation_database import qm.test.suite import qm.test.target import qm.test.test from qm.test.classes.previous_testrun import PreviousTestRun __extension_bases = { 'database' : qm.test.database.Database, 'host' : qm.host.Host, 'label' : qm.label.Label, 'resource' : qm.test.resource.Resource, 'result_reader' : qm.test.result_reader.ResultReader, 'result_stream' : qm.test.result_stream.ResultStream, 'run_database' : qm.test.run_database.RunDatabase, 'expectation_database' : qm.test.expectation_database.ExpectationDatabase, 'suite' : qm.test.suite.Suite, 'target' : qm.test.target.Target, 'test' : qm.test.test.Test } """A map from extension class kinds to base classes. An extension class of a particular 'kind' must be derived from 'extension_bases[kind]'.""" extension_kinds = __extension_bases.keys() """Names of different kinds of QMTest extension classes.""" extension_kinds.sort() __class_caches = {} """A dictionary of loaded class caches. The keys are the kinds in 'extension_kinds'. The associated value is itself a dictionary mapping class names to class objects.""" # Initialize the caches. for kind in extension_kinds: __class_caches[kind] = {} ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/report.py0000664000076400007640000002317411107032225015650 0ustar stefanstefan######################################################################## # # File: report.py # Author: Stefan Seefeld # Date: 2005-02-13 # # Contents: # QMTest ReportGenerator class. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm import qm.xmlutil from qm.common import PythonException from qm.test import base from qm.test.result import Result from qm.test.reader_test_run import ReaderTestRun import xml.sax import sys ######################################################################## # Classes ######################################################################## class ReportGenerator: """A 'ReportGenerator' generates a test report from one or more result files.""" def __init__(self, output, database=None): if output and output != '-': self.output = open(output, 'w+') else: self.output = sys.stdout self.database = database self.__document = qm.xmlutil.create_dom_document( public_id="QMTest/Report", document_element_tag="report") def GenerateReport(self, flat, arguments): """Generates a report file with results collected from a set of result files. 'flat' -- True to indicate a flat result listing, False if tests should be reported according to the database directory structure. 'arguments' -- command arguments of the form [result [-e expectation]]+ returns -- None.""" # Construct a list of (result / expectation file) tuples. # As the expectation file is optional, see whether there # is an '-e' option, and then adjust the remainder accordingly. input = [] while arguments: if len(arguments) >= 3 and arguments[1] == '-e': input.append((arguments[0], arguments[2])) arguments = arguments[3:] else: input.append((arguments[0],None)) arguments = arguments[1:] # Write out the prologue. self.output.write("\n") self.output.write("\n") test_runs = self._LoadTestRuns(input) self.output.write(" \n") for test_run, expectations in test_runs: self.output.write(" \n") annotations = test_run.GetAnnotations() for key, value in annotations.iteritems(): element = self.__document.createElement("annotation") element.setAttribute("key", key) text = self.__document.createTextNode(value) element.appendChild(text) element.writexml(self.output, addindent = " ", newl = "\n") self.output.write(" \n") self.output.write(" \n") if flat: self._ReportFlat(test_runs) else: self._Report(test_runs) self.output.write("\n") def _LoadTestRuns(self, input): """Load test runs from the provided input. 'input' -- A list of pairs of file names referring to result files / expectation files. The expectation file member may be None. returns -- A list of pairs of TestRun objects.""" runs = [] for result_file, exp_file in input: results = None expectations = None try: file = result_file reader = base.load_results(file, self.database) results = ReaderTestRun(reader) if exp_file: file = exp_file reader = base.load_results(file, self.database) expectations = ReaderTestRun(reader) except IOError, e: raise PythonException("Error reading '%s'"%file, IOError, e) except xml.sax.SAXException, e: raise PythonException("Error loading '%s'"%file, xml.sax.SAXException, e) runs.append((results, expectations)) return runs def _GetIds(self, test_runs): """Return a list of ids to report results from. This list is obtained from the database if it is present, or else by taking the union of all items reported in the test runs. 'test_runs' -- A list of result / expectation table pairs. returns -- The tuple of resource-setup-ids, test-ids, and resource-cleanup-ids.""" test_ids = [] resource_setup_ids = [] resource_cleanup_ids = [] if self.database: test_ids = self.database.GetTestIds() resource_setup_ids = self.database.GetResourceIds() resource_cleanup_ids = resource_setup_ids else: for results, e in test_runs: for result in results.GetAllResults("", Result.TEST): if not result.GetId() in test_ids: test_ids.append(result.GetId()) for result in results.GetAllResults("", Result.RESOURCE_SETUP): if not result.GetId() in resource_setup_ids: resource_setup_ids.append(result.GetId()) for result in results.GetAllResults("", Result.RESOURCE_CLEANUP): if not result.GetId() in resource_cleanup_ids: resource_cleanup_ids.append(result.GetId()) return test_ids, resource_setup_ids, resource_cleanup_ids def _ReportFlat(self, test_runs): """Generate test report with the given set of test runs. The report will contain a flat list of item ids. 'test_runs' -- List of pairs of TestRun objects.""" ids = self._GetIds(test_runs) kinds = [Result.TEST, Result.RESOURCE_SETUP, Result.RESOURCE_CLEANUP] element = self.__document.createElement('results') # Report all items, sorted by their kind. for k in [0, 1, 2]: for id in ids[k]: self._ReportItem(kinds[k], id, id, test_runs, element) element.writexml(self.output, indent = " ", addindent = " ", newl = "\n") def _Report(self, test_runs): """Generate test report with the given set of test runs. The report will contain a tree structure with items appearing in their respective subdirectory. 'test_runs' -- List of pairs of TestRun objects.""" element = self.__document.createElement('results') root = self._ReportSubdirectory('', test_runs, element) root.writexml(self.output, indent=" ", addindent=" ", newl="\n") def _ReportSubdirectory(self, directory, test_runs, element=None): """Generate a DOM node for the given directory containing its results. 'directory' -- The directory for which to generate the report node. 'test_runs' -- The List of TestRuns. 'element' -- DOM element to store results into. If this is None, an element will be created. returns -- DOM element node containing the xmlified results.""" if not element: element = self.__document.createElement('subdirectory') element.setAttribute('name', directory) # Start with the subdirectories. for dir in self.database.GetSubdirectories(directory): child = self._ReportSubdirectory(dir, test_runs) element.appendChild(child) # Report all items, sorted by kind. for id in self.database.GetIds('test', directory, False): self._ReportItem('test', id, self.database.SplitLabel(id)[1], test_runs, element) for id in self.database.GetIds('resource', directory, False): self._ReportItem('resource_setup', id, self.database.SplitLabel(id)[1], test_runs, element) self._ReportItem('resource_cleanup', id, self.database.SplitLabel(id)[1], test_runs, element) return element def _ReportItem(self, kind, item_id, name, test_runs, parent): """Report a single item. 'kind' -- The kind of item to report. 'item_id' -- The item id to report. 'name' -- The item's name (usually either the absolute or relative id). 'test_runs' -- The list of test runs. 'parent' -- An XML element to insert new nodes into.""" # Create one item node per id... item = self.__document.createElement('item') item.setAttribute('id', name) item.setAttribute('kind', kind) parent.appendChild(item) # ...and fill it with one result per test run. for results, expectations in test_runs: result = results.GetResult(item_id, kind) if not result: result = Result(kind, item_id, Result.UNTESTED) # Inject two new annotations containing the expectation values. if expectations: exp = expectations.GetResult(item_id, kind) if exp: result['qmtest.expected_outcome'] = exp.GetOutcome() cause = exp.get('qmtest.cause') if cause: result['qmtest.expected_cause'] = cause child = result.MakeDomNode(self.__document) # Remove redundant attributes child.removeAttribute('id') child.removeAttribute('kind') item.appendChild(child) qmtest-2.4.1/qm/test/directory_suite.py0000664000076400007640000000504611107032225017550 0ustar stefanstefan######################################################################## # # File: directory_suite.py # Author: Mark Mitchell # Date: 2001-10-06 # # Contents: # QMTest DirectorySuite class. # # Copyright (c) 2001 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## from qm.test.suite import * ######################################################################## # classes ######################################################################## class DirectorySuite(Suite): """A 'DirectorySuite' is a suite corresponding to a directory. A 'DirectorySuite' is an implicit suite that contains all tests within a given directory. The directory is given by a label, not a file system directory, so a 'DirectorySuite' can work with any database.""" def __init__(self, database, directory): """Construct a new 'DirectorySuite'. 'database' -- The 'Database' instance containing this suite. 'directory' -- A label giving the directory corresponding to this suite.""" # Construct the base class. super(DirectorySuite, self).__init__({}, qmtest_id = directory, qmtest_database = database) def GetTestIds(self): """Return the tests contained in this suite. returns -- A sequence of labels corresponding to the tests contained in this suite. Tests that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.""" return self.GetDatabase().GetTestIds(self.GetId(), scan_subdirs=0) def GetSuiteIds(self): """Return the suites contained in this suite. returns -- A sequence of labels corresponding to the suites contained in this suite. Suites that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.""" return self.GetDatabase().GetSuiteIds(self.GetId(), scan_subdirs=0) def IsImplicit(self): return 1 ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/suite.py0000664000076400007640000001052411107032225015461 0ustar stefanstefan######################################################################## # # File: suite.py # Author: Mark Mitchell # Date: 11/05/2001 # # Contents: # QMTest Suite class # # Copyright (c) 2001 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm import qm.extension ######################################################################## # Classes ######################################################################## class Suite(qm.extension.Extension): """A collection of tests. A test suite is a collection of tests. The suite may contain other suites by reference as well; all tests contained in these contained suites are considered contained in the containing suite as well.""" arguments = [ ] kind = "suite" EXTRA_ID = "qmtest_id" """The name of the extra keyword argument to '__init__' that specifies the name of the test or resource.""" EXTRA_DATABASE = "qmtest_database" """The name of the extra keyword argument to '__init__' that specifies the database containing the test or resource.""" def __init__(self, arguments = None, **args): """Construct a new 'Runnable'. 'arguments' -- As for 'Extension.__init__'. 'args' -- As for 'Extension.__init__'.""" self.__id = args.pop(self.EXTRA_ID) self.__database = args.pop(self.EXTRA_DATABASE) if arguments: args.update(arguments) super(Suite, self).__init__(**args) def GetDatabase(self): """Return the 'Database' that contains this suite. returns -- The 'Database' that contains this suite.""" return self.__database def GetId(self): """Return the ID of this test suite.""" return self.__id def GetTestIds(self): """Return the tests contained in this suite. returns -- A sequence of labels corresponding to the tests contained in this suite. Tests that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.""" return [] def GetSuiteIds(self): """Return the suites contained in this suite. returns -- A sequence of labels corresponding to the suites contained in this suite. Suites that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.""" return [] def IsImplicit(self): """Return true if this is an implicit test suite. Implicit test suites cannot be edited.""" raise NotImplementedError def GetAllTestAndSuiteIds(self): """Return the tests/suites contained in this suite and its subsuites. returns -- A pair '(test_ids, suite_ids)'. The 'test_ids' and 'suite_ids' elements are both sequences of labels. The values returned include all tests and suites that are contained in this suite and its subsuites, recursively.""" suite = self test_ids = [] suite_ids = [] # Maintain a work list of suites to process. work_list = [suite] # Process until the work list is empty. while len(work_list) > 0: suite = work_list.pop(0) # Accumulate test and resource IDs in the suite. test_ids.extend(suite.GetTestIds()) # Find sub suites in the suite. sub_suite_ids = suite.GetSuiteIds() # Accumulate them. suite_ids.extend(sub_suite_ids) # Retrieve the 'Suite' objects. sub_suites = map(self.GetDatabase().GetSuite, sub_suite_ids) # Don't expand ordinary suites contained in implicit suites. if suite.IsImplicit(): sub_suites = filter(lambda s: s.IsImplicit(), sub_suites) # Add contained suites to the work list. work_list.extend(sub_suites) return test_ids, suite_ids qmtest-2.4.1/qm/test/file_result_stream.py0000664000076400007640000000466111107032225020225 0ustar stefanstefan######################################################################## # # File: file_result_stream.py # Author: Mark Mitchell # Date: 04/13/2003 # # Contents: # FileResultStream # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm.common import qm.fields from qm.test.result_stream import ResultStream import sys ######################################################################## # Classes ######################################################################## class FileResultStream(ResultStream): """A 'FileResultStream' writes its output to a file. A 'FileResultStream' is an abstract base class for other result stream classes that store results in a single file. The file to which results should be written can be specified using either the 'filename' argument or the 'file' argument. The latter is for use by QMTest internally.""" arguments = [ qm.fields.TextField( name = "filename", title = "File Name", description = """The name of the file. All results will be written to the file indicated. If no filename is specified, or the filename specified is "-", the standard output will be used.""", verbatim = "true", default_value = ""), qm.fields.PythonField( name = "file"), ] _is_binary_file = 0 """If true, the file written is a binary file. This flag can be overridden by derived classes.""" def __init__(self, arguments = None, **args): ResultStream.__init__(self, arguments, **args) if not self.file: if self.filename and self.filename != "-": # Open the file in unbuffered mode so that results will be # written out immediately. if self._is_binary_file: mode = "wb" else: mode = "w" self.file = open(self.filename, mode, 0) # Child processes do not need to write to the results # file. qm.common.close_file_on_exec(self.file) else: self.file = sys.stdout qmtest-2.4.1/qm/test/result_stream.py0000664000076400007640000000677011107032225017231 0ustar stefanstefan######################################################################## # # File: result_stream.py # Author: Mark Mitchell # Date: 2001-10-10 # # Contents: # QMTest ResultStream class. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import qm import qm.extension import qm.fields from qm.test.result import Result ######################################################################## # classes ######################################################################## class ResultStream(qm.extension.Extension): """A 'ResultStream' displays test results. A 'ResultStream' is responsible for displaying test results for the user as they arrive. It may also display summary information when the results are complete. The 'ResultStream' may also choose to write the results to a file for permanent storage. 'ResultStream' is an abstract class. """ kind = "result_stream" expected_outcomes = qm.fields.PythonField() def __init__(self, arguments = None, **args): if arguments: args.update(arguments) super(ResultStream, self).__init__(**args) def WriteAnnotation(self, key, value): """Output an annotation for this run. Subclasses should override this if they want to store/display annotations; the default implementation simply discards them. 'key' -- the key value as a string. 'value' -- the value of this annotation as a string.""" pass def WriteAllAnnotations(self, annotations): """Output all annotations in 'annotations' to this stream. Currently this is the same as making repeated calls to 'WriteAnnotation', but in the future, as special annotation types like timestamps are added, this will do the work of dispatching to functions like 'WriteTimestamp'. Should not be overridden by subclasses.""" for key, value in annotations.iteritems(): self.WriteAnnotation(key, value) def WriteResult(self, result): """Output a test result. Subclasses must override this method; the default implementation raises a 'NotImplementedError'. 'result' -- A 'Result'.""" raise NotImplementedError def Summarize(self): """Output summary information about the results. When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point. Derived class methods may override this method. They should, however, invoke this version before returning.""" pass def _GetExpectedOutcome(self, test_id): """Return the outcome expected for 'test_id'. returns -- The outcome (one of the elements of 'Result.outcomes') expected for 'test_id'. The expected outcome is taken from the 'expected_outcomes' provided when constructing this result stream, if available. If no expected outcome is available the default value ('Result.PASS') will be returned.""" return self.expected_outcomes.get(test_id, Result.PASS) qmtest-2.4.1/qm/test/test.py0000664000076400007640000001734311107032225015315 0ustar stefanstefan######################################################################## # # File: test.py # Author: Mark Mitchell # Date: 2001-10-10 # # Contents: # QMTest Test class. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm import qm.fields import qm.test.database import qm.test.result import qm.test.runnable ######################################################################## # Variables ######################################################################## __the_targets = [] """The global set of available targets.""" ######################################################################## # Classes ######################################################################## class TargetGroupField(qm.fields.TextField): """A 'TargetGroupField' contains a target group pattern. A target group pattern is a regular expression. A test will only be run on a particular target if the target's group is matched by the test's target group pattern.""" def GetDescription(self): """Return a description of this field. This description is used when displaying detailed help information about the field.""" # Get the basic description. desc = qm.fields.TextField.GetDescription(self) # Add a list of the available targets. desc = desc + "\n\n**Available Target Groups**\n\n" groups = [t.GetGroup() for t in get_targets()] for g in groups: desc = desc + " * " + g + "\n" return desc class Test(qm.test.runnable.Runnable): """A 'Test' is run to check for correct behavior. A 'Test' performs some check on the system being tested, and indicates whether the check was successful, or whether the check failed. Each test class (i.e., class derived from 'Test') describes a set of "arguments". Each argument has a name and a type. The values of these arguments determine the design-time parameters for the test. For example, for a test class that executes program and checks their exit codes, the arguments might consist of the name of the program to execute, and the command-line arguments that should be given to that program. QMTest uses the arguments to prompt the user when creating a new test. Each test class also defines a 'Run' method that indicates how to run tests in that class. The 'Run' method is responsible for actually performing the test and for reporting the results. 'Test' is an abstract class. You can extend QMTest by providing your own test class implementation. If the test classes that come with QMTest cannot be used conveniently with your application domain, or if you would like to report more detailed information about passing and failing tests, you may wish to create a new test class. To create your own test class, you must create a Python class derived (directly or indirectly) from 'Test'. The documentation for each method of 'Test' indicates whether you must override it in your test class implementation. Some methods may be overridden, but do not need to be. You might want to override such a method to provide a more efficient implementation, but QMTest will work fine if you just use the default version. If QMTest calls a method on a test and that method raises an exception that is not caught within the method itself, QMTest will catch the exception and continue processing.""" class OutcomeField(qm.fields.EnumerationField): """An 'OutcomeField' contains an outcome.""" def __init__(self, name, **properties): qm.fields.EnumerationField.__init__( self, name, qm.test.result.Result.PASS, [ qm.test.result.Result.PASS, qm.test.result.Result.FAIL, qm.test.result.Result.UNTESTED, qm.test.result.Result.ERROR ], **properties) class TestField(qm.fields.ChoiceField): """A 'TestField' contains the name of a test. The exact format of the name depends on the test database in use.""" def GetItems(self): database = qm.test.database.get_database() return database.GetTestIds() arguments = [ TargetGroupField( name="target_group", title="Target Group Pattern", description="""The targets on which this test can run. A regular expression that indicates the targets on which this test can be run. If the pattern matches a particular group name, the test can be run on targets in that group.""", default_value=".*" ), qm.fields.SetField( qm.fields.TupleField( "prerequisites", (TestField( name = "test_id", title = "Test", description = """The name of the prerequisite test.""", default_value = "", ), OutcomeField( name = "outcome", title = "Outcome", description \ = """The required outcome for the prerequisite test. If the outcome is different from that given here, the dependent test will not be run.""", )), title="Prerequisite Tests", description="""The tests on which this test depends. Every test can depend on other tests. Those tests will be run before this test. If the prerequisite test does not have the outcome indicated, this test will not be run.""", )) ] kind = "test" PREREQUISITES_FIELD_ID = "prerequisites" """The name of the field that contains the prerequisites on which this test depends.""" def Run(self, context, result): """Run the test. 'context' -- A 'Context' giving run-time parameters to the test. 'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations. This method should not return a value. Derived classes must override this method.""" raise NotImplementedError def GetTargetGroup(self): """Returns the pattern for the targets that can run this test. returns -- A regular expression (represented as a string) that indicates the targets on which this test can be run. If the pattern matches a particular group name, the test can be run on targets in that group.""" return self.target_group ######################################################################## # Functions ######################################################################## def set_targets(targets): """Set the available target. 'targets' -- A list of targets available for test execution.""" global __the_targets __the_targets = targets def get_targets(): """Get the available target. returns -- A list of targets available for test execution.""" return __the_targets ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/test/command_thread.py0000664000076400007640000001137411107032225017301 0ustar stefanstefan######################################################################## # # File: command_thread.py # Author: Mark Mitchell # Date: 01/02/2002 # # Contents: # CommandThread # # Copyright (c) 2002 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm import Queue from threading import * import sys import types ######################################################################## # Classes ######################################################################## class CommandThread(Thread): """A 'CommandThread' is a thread that executes commands. The commands are written to a 'Queue' by a controlling thread. The 'CommandThread' extracts the commands and dispatches them to derived class methods that process them. This class is used as a base class for thread classes used by some targets. The commands are written to the 'Queue' as Python objects. The normal commands have the form '(method, descriptor, context)' where 'method' is a string. At present, the only value used for 'method' is '_RunTest'. In that case 'descriptor' is a test descriptor and 'context' is a 'Context'. The 'Stop' command is provided as a simple string, not a tuple.""" def __init__(self, target): """Construct a new 'CommandThread'. 'target' -- The 'Target' that owns this thread.""" Thread.__init__(self, None, None, None) # Remember the target. self.__target = target # Create the queue to which the controlling thread will # write commands. self.__command_queue = Queue.Queue(0) def run(self): """Execute the thread.""" try: # Process commands from the queue, until the "quit" # command is received. while 1: # Read the command. command = self.__command_queue.get() # If the command is just a string, it should be # the 'Stop' command. if isinstance(command, types.StringType): assert command == "Stop" self._Trace("Received stop command") self._Stop() break # Decompose command. method, desc, context = command assert method == "_RunTest" # Run it. self._Trace("About to run test " + desc.GetId()) self._RunTest(desc, context) self._Trace("Finished running test " + desc.GetId()) except: # Exceptions should not occur in the above loop. However, # in the event that one does occur it is easier to debug # QMTest is the exception is written out. exc_info = sys.exc_info() sys.stderr.write(qm.common.format_exception(exc_info)) assert 0 def GetTarget(self): """Return the 'Target' associated with this thread. returns -- The 'Target' with which this thread is associated. Derived classes must not override this method.""" return self.__target def RunTest(self, descriptor, context): """Run the test given by 'descriptor'. 'descriptor' -- The 'TestDescriptor' for the test to be run. 'context' -- The 'Context' in which to run the test. This method is called by the controlling thread. Derived classes must not override this method.""" self.__command_queue.put(("_RunTest", descriptor, context)) def Stop(self): """Stop the thread. Derived classes must not override this method.""" self.__command_queue.put("Stop") def _RunTest(self, descriptor, context): """Run the test given by 'descriptor'. 'descriptor' -- The 'TestDescriptor' for the test to be run. 'context' -- The 'Context' in which to run the test. Derived classes must override this method.""" raise NotImplementedError def _Stop(self): """Stop the thread. This method is called in the thread after 'Stop' is called from the controlling thread. Derived classes can use this method to release resources before the thread is destroyed. Derived classes may override this method.""" pass def _Trace(self, message): """Write a trace 'message'. 'message' -- A string to be output as a trace message.""" if __debug__: tracer = qm.test.cmdline.get_qmtest().GetTracer() tracer.Write(message, "command_thread") qmtest-2.4.1/qm/test/expectation_database.py0000664000076400007640000000337011107032225020500 0ustar stefanstefan######################################################################## # # File: expectation_database.py # Author: Stefan Seefeld # Date: 2006-11-05 # # Contents: # QMTest ExpectationDatabase class. # # Copyright (c) 2006 by CodeSourcery, Inc. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.extension import Extension from qm.fields import PythonField from qm.test.result import Result ######################################################################## # Classes ######################################################################## class ExpectationDatabase(Extension): """An 'ExpectationDatabase' stores result expectations. An 'ExpectationDatabase' provides a mechanism to store and make accessible expectations for test outcomes. By default, all tests are expected to pass. """ kind = 'expectation_database' test_database = PythonField() testrun_parameters = PythonField() def Lookup(self, test_id): """Look up the expected outcome for the given test. 'test_id' -- test-id for which the outcome is queried. returns -- a Result object associated with this test_id.""" return Result(Result.TEST, test_id) def GetExpectedOutcomes(self): """Return a dict object mapping test ids to expected outcomes.""" outcomes = {} if self.test_database: for test_id in self.test_database.GetTestIds(): outcomes[test_id] = self.Lookup(test_id).GetOutcome() return outcomes qmtest-2.4.1/qm/test/file_database.py0000664000076400007640000004541511107032225017102 0ustar stefanstefan######################################################################## # # File: file_database.py # Author: Mark Mitchell # Date: 2001-10-05 # # Contents: # FileDatabase # ExtensionDatabase # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import dircache import os import os.path from qm.test.database import * from qm.test.directory_suite import * ######################################################################## # Classes ######################################################################## class FileDatabase(Database): """A 'FileDatabase' stores each test as a single file. A 'FileDatabase' is a 'Database' that stores each test, suite, or resource as a single file. In addition, some subdirectories can be considered implicit suites. The contents of the implicit suite are all of the tests and suites contained in the subdirectory. 'FileDatabase' is an abstract class.""" # Methods that deal with tests. def GetTest(self, test_id): """Return the 'TestDescriptor' for the test named 'test_id'. 'test_id' -- A label naming the test. returns -- A 'TestDescriptor' corresponding to 'test_id'. raises -- 'NoSuchTestError' if there is no test in the database named 'test_id'.""" path = self.GetTestPath(test_id) if not self._IsTestFile(path): raise NoSuchTestError, test_id return self._GetTestFromPath(test_id, os.path.normpath(path)) def GetTestPath(self, test_id): """Return the file containing 'test_id'. 'test_id' -- The name of a test. returns -- The absolute file name of the file that contains, or would contain, 'test_id'. This method works even if no test named 'test_id' exists. Derived classes may override this method.""" return self._GetPathFromLabel(test_id) def _IsTestFile(self, path): """Returns true if 'path' is a test file. 'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels. returns -- True iff the file corresponds to a test. Derived classes must override this method.""" raise NotImplementedError # Methods that deal with suites. def GetSuite(self, suite_id): """Return the 'Suite' for the suite named 'suite_id'. 'suite_id' -- A label naming the suite. returns -- An instance of 'Suite' (or a derived class of 'Suite') corresponding to 'suite_id'. raises -- 'NoSuchSuiteError' if there is no suite in the database named 'suite_id'.""" path = self.GetSuitePath(suite_id) if not self._IsSuiteFile(path): raise NoSuchSuiteError, suite_id # There are two kinds of suites: directories (which are # implicit suites), and files (which are explicit suites). if os.path.isdir(path): return DirectorySuite(self, suite_id) else: return self._GetSuiteFromPath(suite_id, os.path.normpath(path)) def GetSuitePath(self, suite_id): """Return the file containing 'suite_id'. 'suite_id' -- The name of a suite. returns -- The absolute file name of the file (or directory) that contains, or would contain, 'suite_id'. This method works even if no suite named 'suite_id' exists. Derived classes may override this method.""" return self._GetPathFromLabel(suite_id) def _IsSuiteFile(self, path): """Returns true if 'path' is a test suite file or directory. 'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels. returns -- True iff the file corresponds to a test. Derived classes may override this method, but only to restrict the set of suites. In particular, a derived class method may return false where this method would return true, but never vice versa. Derived classes must override this method.""" raise NotImplementedError # Methods that deal with resources. def GetResource(self, resource_id): """Return the 'ResourceDescriptor' for the resource named 'resource_id'. 'resource_id' -- A label naming the resource. returns -- A 'ResourceDescriptor' corresponding to 'resource_id'. raises -- 'NoSuchResourceError' if there is no resource in the database named 'resource_id'.""" path = self.GetResourcePath(resource_id) if not self._IsResourceFile(path): raise NoSuchResourceError, resource_id return self._GetResourceFromPath(resource_id, os.path.normpath(path)) def GetResourcePath(self, resource_id): """Return the file containing 'resource_id'. 'resource_id' -- The name of a resource. returns -- The absolute file name of the file that contains, or would contain, 'resource_id'. This method works even if no Resource named 'resource_id' exists. Derived classes may override this method.""" return self._GetPathFromLabel(resource_id) def _IsResourceFile(self, path): """Returns true if 'path' is a resource file. 'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels. returns -- True iff the file corresponds to a resource. Derived classes must override this method.""" raise NotImplementedError # Miscellaneous methods. def GetRoot(self): """Return the root of the test database. returns -- The directory that serves as the root of the test database. All paths are relative to this directory. Derived classes may override this method.""" return self.GetPath() def GetSubdirectories(self, directory): """Return the subdirectories of 'directory'. 'directory' -- A label indicating a directory in the database. returns -- A sequence of (relative) labels indictating the subdirectories of 'directory'. For example, if "a.b" and "a.c" are directories in the database, this method will return "b" and "c" given "a" as 'directory'.""" subdirs = [] file_dir = self.GetSuitePath(directory) for entry in dircache.listdir(file_dir): if not self._AreLabelsPaths(): root = os.path.splitext(entry)[0] else: root = entry if not self.IsValidLabel(root): continue entry_path = os.path.join(file_dir, entry) if (self._IsSuiteFile(entry_path) and os.path.isdir(entry_path)): subdirs.append(root) return subdirs def GetIds(self, kind, directory = "", scan_subdirs = 1): # Compute the path name of the directory in which to start. file_dir = self.GetSuitePath(directory) # Get all the files of the appropriate kind. return self._GetLabels(file_dir, scan_subdirs, directory, lambda p: self._IsFile(kind, p)) def _GetPath(self, kind, id): """Returns the file system path corresponding to 'id'. 'kind' -- An extension kind. 'id' -- The name of the entity. returns -- The path in which the entity is stored.""" return { Database.RESOURCE : self.GetResourcePath, Database.TEST : self.GetTestPath, Database.SUITE : self.GetSuitePath } [kind] (id) def _IsFile(self, kind, path): """Returns true if 'path' is a file of the indicated 'kind'. 'kind' -- One of 'Database.ITEM_KINDS'. 'path' -- The path to a file. returns -- True iff 'path' is a file of the indicated kind. Derived classes must override this method.""" return { Database.TEST : self._IsTestFile, Database.RESOURCE : self._IsResourceFile, Database.SUITE : self._IsSuiteFile } [kind] (path) # Derived classes must override these methods. def _GetTestFromPath(self, test_id, path): """Return a descriptor for the test given by 'path'. 'test_id' -- The label naming the test. 'path' -- An absolute path to a test file. The 'path' satisfies '_IsTestFile'. returns -- A 'TestDescriptor' corresponding to 'test_id'. Derived classes must override this method.""" raise NotImplementedError def _GetSuiteFromPath(self, suite_id, path): """Return a the 'Suite' given by 'path'. 'suite_id' -- The label naming the suite. 'path' -- An absolute path to a suite file. The 'path' satisfies '_IsSuiteFile' and is a file, not a directory. returns -- A 'Suite' corresponding to 'suite_id'. Derived classes must override this method.""" raise NotImplementedError def _GetResourceFromPath(self, resource_id, path): """Return a descriptor for the resource given by 'path'. 'resource_id' -- The label naming the resource. 'path' -- An absolute path to a resource file. The 'path' satisfies '_IsResourceFile'. returns -- A 'ResourceDescriptor' corresponding to 'resource_id'. Derived classes must override this method.""" raise NotImplementedError def _GetPathFromLabel(self, label): """Returns the file system path corresponding to 'label'. 'label' -- The id for a test, test suite, or similar entity. returns -- The absolute path for the corresponding entry in the file system, but without any required extension.""" return os.path.join(self.GetRoot(), self._GetRelativeLabelPath(label)) def _GetLabelFromBasename(self, basename): """Returns the label associated with a file named 'basename'. 'basename' -- The basename of a file, including the extension. returns -- The corresponding label. Derived classes may override this method.""" return basename def _GetLabels(self, directory, scan_subdirs, label, predicate): """Returns the labels of entities in 'directory'. 'directory' -- The absolute path name of the directory in which to begin the search. 'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned. 'label' -- The label that corresponds to 'directory'. 'predicate' -- A function that takes a file name and returns a boolean. returns -- Labels for all file names in 'directory'. that satisfy 'predicate' If 'scan_subdirs' is true, subdirectories are scanned as well.""" labels = [] # Go through all of the files (and subdirectories) in that # directory. for entry in dircache.listdir(directory): entry_label = self._GetLabelFromBasename(entry) # If the label is not valid then pretend it # does not exist. It would not be valid to create an entity # with such an id. if not self.IsValidLabel(entry_label): continue # Compute the full path to 'entry'. entry_path = os.path.join(directory, entry) # If it satisfies the 'predicate', add it to the list. if predicate(entry_path): labels.append(self.JoinLabels(label, entry_label)) # If it is a subdirectory, recurse. if (scan_subdirs and os.path.isdir(entry_path) and self._IsSuiteFile(entry_path)): labels.extend(self._GetLabels(entry_path, scan_subdirs, self.JoinLabels(label, entry_label), predicate)) return labels def RemoveExtension(self, id, kind): path = self._GetPath(kind, id) if not os.path.isfile(path): raise { Database.RESOURCE : NoSuchResourceError, Database.TEST: NoSuchTestError, Database.SUITE: NoSuchSuiteError }[kind], id os.remove(path) def _AreLabelsPaths(self): """Returns true if labels are to be thought of as file names. returns -- True if labels are to be thought of as file names. If this predicate holds, every label is a path, relative to the root of the database. If false, the labels are translated to paths by adding the 'suite_extension' between directories and the 'test_extension' or 'resource_extension' at the end of the name.""" return self.label_class == "file_label.FileLabel" def _GetRelativeLabelPath(self, label): """Returns a representation of 'label' as a relative filename. returns -- A relative filename corresponding to 'label'.""" if self._AreLabelsPaths(): return label return os.path.join(*self.GetLabelComponents(label)) class ExtensionDatabase(FileDatabase): """An 'ExtensionDatabase' is a 'FileDatabase' where each kind of entity (test, suite, resource) has a particular extension. For example, if tests have the extension '.qmt', then all files ending with '.qmt' are considered tests. If an extension for a particular kind of entity is not specified or is the empty string, then all files will be considered to be that kind of entity. 'ExtensionDatabase' is an abstract class.""" arguments = [ qm.fields.TextField( name="test_extension", title="Test Extension", description="""The extension for test files. The extension (including the leading period) used for files containing tests.""", default_value=".qmt"), qm.fields.TextField( name="suite_extension", title="Suite Extension", description="""The extension for suite files. The extension (including the leading period) used for files containing suites.""", default_value=".qms"), qm.fields.TextField( name="resource_extension", title="Resource Extension", description="""The extension for resource files. The extension (including the leading period) used for files containing resources.""", default_value=".qma"), ] def __init__(self, path, arguments = None, **args): super(ExtensionDatabase, self).__init__(path, arguments, **args) self._extensions = { Database.TEST : self.test_extension, Database.RESOURCE : self.resource_extension, Database.SUITE : self.suite_extension } def GetTestExtension(self): """Return the extension that indicates a file is a test. returns -- The extension (including the leading period) that indicates that a file is a test.""" return self.test_extension def GetSuiteExtension(self): """Return the extension that indicates a file is a suite. returns -- The extension (including the leading period) that indicates that a file is a suite.""" return self.suite_extension def GetResourceExtension(self): """Return the extension that indicates a file is a resource. returns -- The extension (including the leading period) that indicates that a file is a resource.""" return self.resource_extension def GetTestPath(self, test_id): test_path = self._GetPathFromLabel(test_id) if not self._AreLabelsPaths(): test_path += self.test_extension return test_path def _IsTestFile(self, path): extension = self.GetTestExtension() if extension: e = os.path.splitext(path)[1] if e != extension: return 0 return os.path.isfile(path) def GetSuitePath(self, suite_id): # The top-level suite is just the directory containing the # database; no extension is required. if suite_id == "": return self.GetRoot() else: suite_path = self._GetPathFromLabel(suite_id) if not self._AreLabelsPaths(): suite_path += self.suite_extension return suite_path def _IsSuiteFile(self, path): if path == self.GetRoot(): return 1 extension = self.GetSuiteExtension() if extension: e = os.path.splitext(path)[1] if e != extension: return 0 return os.path.isfile(path) or os.path.isdir(path) def GetResourcePath(self, resource_id): test_path = self._GetPathFromLabel(resource_id) if not self._AreLabelsPaths(): test_path += self.resource_extension return test_path def _IsResourceFile(self, path): extension = self.GetResourceExtension() if extension: e = os.path.splitext(path)[1] if e != extension: return 0 return os.path.isfile(path) def _GetPathFromLabel(self, label): if self._AreLabelsPaths(): path = label else: path = self._GetRelativeLabelPath(label) return os.path.join(self.GetRoot(), path) def _GetLabelFromBasename(self, basename): if self._AreLabelsPaths(): return basename else: return os.path.splitext(basename)[0] def _GetRelativeLabelPath(self, label): """Returns a representation of 'label' as a filename. returns -- A filename corresponding to 'label'.""" if self._AreLabelsPaths(): return label path = "" components = self.GetLabelComponents(label) if not components: return path for c in components[:-1]: path = os.path.join(path, c + self.suite_extension) path = os.path.join(path, components[-1]) return path ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/web.py0000664000076400007640000024531511120046774014147 0ustar stefanstefan######################################################################## # # File: web.py # Author: Alex Samuel # Date: 2001-02-08 # # Contents: # Common code for implementing web user interfaces. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## """Common code for implementing web user interfaces.""" ######################################################################## # imports ######################################################################## import BaseHTTPServer import cgi import diagnostic import errno import htmlentitydefs import os import os.path import common import qm.platform import qm.user import re import SimpleHTTPServer import SocketServer import socket import string import structured_text import sys import temporary_directory import time import traceback import types import urllib import user import random import qm.external.DocumentTemplate as DocumentTemplate sys.path.insert(1, os.path.dirname(DocumentTemplate.__file__)) ######################################################################## # constants ######################################################################## session_id_field = "session" """The name of the form field used to store the session ID.""" ######################################################################## # exception classes ######################################################################## class AddressInUseError(common.QMException): pass class PrivilegedPortError(common.QMException): pass class NoSessionError(common.QMException): pass class InvalidSessionError(common.QMException): pass ######################################################################## # classes ######################################################################## class DtmlPage: """Base class for classes to generate web pages from DTML. The 'DtmlPage' object is used as the variable context when generating HTML from DTML. Attributes and methods are available as variables in DTML expressions. This base class contains common variables and functions that are available when generating all DTML files. To generate HTML from a DTML template, instantiate a 'DtmlPage' object, passing the name of the DTML template file to the initializer function (or create a subclass which does this automatically). Additional named attributes specified in the initializer functions are set as attributes of the 'DtmlPage' object, and thus available as variables in DTML Python expressions. To generate HTML from the template, use the '__call__' method, passing a 'WebRequest' object representing the request in response to which the HTML page is being generated. The request set as the 'request' attribute of the 'DtmlPage' object. The 'WebRequest' object may be omitted, if the generated HTML page is generic and requires no information specific to the request or web session; in this case, an empty request object is used. This class also has an attribute, 'default_class', which is the default 'DtmlPage' subclass to use when generating HTML. By default, it is initialized to 'DtmlPage' itself, but applications may derive a 'DtmlPage' subclass and point 'default_class' to it to obtain customized versions of standard pages.""" html_stylesheet = "/stylesheets/qm.css" """The URL for the cascading stylesheet to use with generated pages.""" common_javascript = "/common.js" qm_bug_system_url = "mailto:qmtest@codesourcery.com" """The public URL for the bug tracking system for the QM tools.""" def __init__(self, dtml_template, **attributes): """Create a new page. 'dtml_template' -- The file name of the DTML template from which the page is generated. The file is assumed to reside in the 'dtml' subdirectory of the configured share directory. '**attributes' -- Additional attributes to include in the variable context.""" self.__dtml_template = dtml_template for key, value in attributes.items(): setattr(self, key, value) def __call__(self, request=None): """Generate an HTML page from the DTML template. 'request' -- A 'WebRequest' object containing a page request in response to which an HTML page is being generated. Session information from the request may be used when generating the page. The request may be 'None', if none is available. returns -- The generated HTML text.""" # Use an empty request if none was specified. if request is None: request = WebRequest("?") self.request = request # Construct the path to the template file. DTML templates are # stored in the 'dtml' subdirectory of the share directory. template_path = os.path.join(qm.get_share_directory(), "dtml", self.__dtml_template) # Generate HTML from the template. html_file = DocumentTemplate.HTMLFile(template_path) return html_file(self) def GetProgramName(self): """Return the name of this application program.""" return common.program_name def GetMainPageUrl(self): """Return the URL for the main page.""" return "/" def WebRequest(self, script_url, **fields): """Convenience constructor for 'WebRequest' objects. Constructs a 'WebRequest' using the specified 'script_url' and 'fields', using the request associated with this object as the base request.""" return apply(WebRequest, (script_url, self.request), fields) def GenerateXMLHeader(self): """Return the XML header for the document.""" return \ ''' ''' def GenerateHtmlHeader(self, description, headers=""): """Return the header for an HTML document. 'description' -- A string describing this page. 'headers' -- Any additional HTML headers to place in the '' section of the HTML document.""" return \ ''' %s %s: %s ''' % (headers, self.html_stylesheet, self.GetProgramName(), self.GetProgramName(), description) def GenerateStartBody(self, decorations=1): """Return markup to start the body of the HTML document.""" return "" def GenerateEndBody(self, decorations=1): """Return markup to end the body of the HTML document.""" result = """

""" return result + self.GenerateStartScript(self.common_javascript) \ + self.GenerateEndScript() + "" def GenerateStartScript(self, uri=None): """Return the HTML for beginning a script. 'uri' -- If not None, a string giving the URI of the script. returns -- A string consisting of HTML for beginning an embedded script. 'GenerateEndScript' must be called later to terminate the script.""" # XHTML does not allow the "language" attribute but Netscape 4 # requires it. Also, in XHTML we should bracked the included # script as CDATA, but that does not work with Netscape 4 # either. result = '' def MakeLoginForm(self, redirect_request=None, default_user_id=""): if redirect_request is None: # No redirection specified, so redirect back to this page. redirect_request = self.request request = redirect_request.copy("login") request["_redirect_url"] = redirect_request.GetUrl() # Use a POST method to submit the login form, so that passwords # don't appear in web logs. form = request.AsForm(method="post", name="login_form") form = form + \ '''
User name:
Password:
''' % default_user_id return form def MakeButton(self, title, script_url, css_class=None, **fields): """Generate HTML for a button to load a URL. 'title' -- The button title. 'script_url' -- The URL of the script. 'fields' -- Additional fields to add to the script request. 'css_class' -- The CSS class to use for the button, or 'None'. The resulting HTML must be included in a form.""" request = apply(WebRequest, [script_url, self.request], fields) return make_button_for_request(title, request, css_class) def MakeImageUrl(self, image): """Generate a URL for an image.""" return "/images/%s" % image def MakeSpacer(self, width=1, height=1): """Generate a spacer. 'width' -- The width of the spacer, in pixels. 'height' -- The height of the spacer, in pixels. returns -- A transparent image of the requested size.""" # 'clear.gif' is an image file containing a single transparent # pixel, used for generating fixed spacers return '' \ % (width, height, self.MakeImageUrl("clear.gif")) def MakeRule(self, color="black"): """Generate a plain horizontal rule.""" return '''
%s
''' % (color, self.MakeSpacer()) def UserIsInGroup(self, group_id): """Return true if the user is a member of group 'group_id'. Checks the group membership of the user associated with the current session. If there is no group named 'group_id' in the user database, returns a false result.""" user_id = self.request.GetSession().GetUserId() try: group = user.database.GetGroup(group_id) except KeyError: # No such group. return 0 else: return user_id in group DtmlPage.default_class = DtmlPage """Set the default DtmlPage implementation to the base class.""" DtmlPage.web = sys.modules[DtmlPage.__module__] """Make the functions in this module accessible.""" class HttpRedirect(Exception): """Exception signalling an HTTP redirect response. A script registered with a 'WebServer' instance can raise this exception instead of returning HTML source text, to indicate that the server should send an HTTP redirect (code 302) response to the client instead of the usual code 202 response. The exception argument is the URL of the redirect target. The 'request' attribute contains a 'WebRequest' for the redirect target.""" def __init__(self, redirect_target_request): """Construct a redirection exception. 'redirect_target_request' -- The 'WebRequest' to which to redirect the client.""" # Initialize the base class. Exception.__init__(self, redirect_target_request.AsUrl()) # Store the request itself. self.request = redirect_target_request class WebRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler): """Handler for HTTP requests. This class groups callback functions that are invoked in response to HTTP requests by 'WebServer'. Don't define '__init__' or store any persistent information in this class or subclasses; a new instance is created for each request. Instead, store the information in the server instance, available through the 'server' attribute.""" # Update the extensions_map so that files are mapped to the correct # content-types. SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map.update( { '.css' : 'text/css', '.js' : 'text/javascript' } ) def do_GET(self): """Process HTTP GET requests.""" # Parse the query string encoded in the URL, if any. script_url, fields = parse_url_query(self.path) # Build a request object and hand it off. request = apply(WebRequest, (script_url, ), fields) # Store the client's IP address with the request. request.client_address = self.client_address[0] self.__HandleRequest(request) def do_POST(self): """Process HTTP POST requests.""" # Determine the post's content type. if self.headers.typeheader is None: content_type_header = self.headers.type else: content_type_header = self.headers.typeheader content_type, params = cgi.parse_header(content_type_header) # We only know how to handle form-data submissions. if content_type == "multipart/form-data": # Parse the form data. fields = cgi.parse_multipart(self.rfile, params) # For each field, take the first value, discarding others. # We don't support multi-valued fields. for name, value in fields.items(): if len(value) == 1: fields[name] = value[0] # There may be additional query arguments in the URL, so # parse that too. script_url, url_fields = parse_url_query(self.path) # Merge query arguments from the form and from the URL. fields.update(url_fields) # Create and process a request. request = apply(WebRequest, (script_url, ), fields) # Store the client's IP address with the request. request.client_address = self.client_address[0] self.__HandleRequest(request) else: self.send_response(400, "Unexpected request (POST of %s)." % content_type) def __HandleScriptRequest(self, request): try: # Execute the script. The script returns the HTML # text to return to the client. try: script_output = self.server.ProcessScript(request) except NoSessionError, msg: script_output = self.server.HandleNoSessionError(request, msg) except InvalidSessionError, msg: script_output = generate_login_form(request, msg) except HttpRedirect, redirection: # The script requested an HTTP redirect response to # the client. self.send_response(302) self.send_header("Location", str(redirection)) self.end_headers() return except SystemExit: self.server.RequestShutdown() script_output = ("%s shutdown." % qm.common.program_name) except: # Oops, the script raised an exception. Show # information about the exception instead. script_output = format_exception(sys.exc_info()) # Send its output. if isinstance(script_output, types.StringType): # The return value from the script is a string. Assume it's # HTML text, and send it appropriate.ly. mime_type = "text/html" data = script_output elif isinstance(script_output, types.TupleType): # The return value from the script is a tuple. Assume the # first element is a MIME type and the second is result # data. mime_type, data = script_output else: raise ValueError self.send_response(200) self.send_header("Content-Type", mime_type) self.send_header("Content-Length", len(data)) # Since this is a dynamically-generated page, indicate that it # should not be cached. The second header is necessary to support # HTTP/1.0 clients. self.send_header("Cache-Control", "no-cache") self.send_header("Pragma", "no-cache") self.end_headers() try: self.wfile.write(data) except IOError: # Couldn't write to the client. Oh well, it's probably a # nework problem, or the user cancelled the operation, or # the browser crashed... pass def __HandleFileRequest(self, request, path): # There should be no query arguments to a request for an # ordinary file. if len(request.keys()) > 0: self.send_error(400, "Unexpected request.") return # Open the file. try: file = open(path, "rb") except IOError: # Send a generic 404 if there's a problem opening the file. self.send_error(404, "File not found.") return # Send the file. self.send_response(200) self.send_header("Content-Type", self.guess_type(path)) self.send_header("Cache-Control", "public") self.end_headers() self.copyfile(file, self.wfile) def __HandlePageCacheRequest(self, request): """Process a retrieval request from the global page cache.""" # Get the page from the cache. page = self.server.GetCachedPage(request) # Send it. self.send_response(200) self.send_header("Content-Type", "text/html") self.send_header("Content-Length", str(len(page))) self.send_header("Cache-Control", "public") self.end_headers() self.wfile.write(page) def __HandleSessionCacheRequest(self, request): """Process a retrieval request from the session page cache.""" # Extract the session ID. session_id = request.GetSessionId() if session_id is None: # We should never get request for pages from the session # cache without a session ID. self.send_error(400, "Missing session ID.") return # Get the page from the cache. page = self.server.GetCachedPage(request, session_id) # Send it. self.send_response(200) self.send_header("Content-Type", "text/html") self.send_header("Content-Length", str(len(page))) self.send_header("Cache-Control", "private") self.end_headers() self.wfile.write(page) def __HandleRequest(self, request): """Process a request from a GET or POST operation. 'request' -- A 'WebRequest' object.""" if request.GetScriptName() == _page_cache_name: # It's a request from the global page cache. self.__HandlePageCacheRequest(request) elif request.GetScriptName() == _session_cache_name: # It's a request from the session page cache. self.__HandleSessionCacheRequest(request) # Check if this request corresponds to a script. elif self.server.IsScript(request): # It is, so run it. self.__HandleScriptRequest(request) else: # Now check if it maps onto a file. Translate the script URL # into a file system path. path = self.server.TranslateRequest(request) # Is it a file? if path is not None and os.path.isfile(path): self.__HandleFileRequest(request, path) else: # The server doesn't know about this URL. self.send_error(404, "File not found.") def log_message(self, format, *args): """Log a message; overrides 'BaseHTTPRequestHandler.log_message'.""" # Write an Apache-style log entry via the server instance. message = "%s - - [%s] %s\n" \ % (self.address_string(), self.log_date_time_string(), format%args) self.server.LogMessage(message) class HTTPServer(BaseHTTPServer.HTTPServer): """Workaround for problems in 'BaseHTTPServer.HTTPServer'. The Python 1.5.2 library's implementation of 'BaseHTTPServer.HTTPServer.server_bind' seems to have difficulties when the local host address cannot be resolved by 'gethostbyaddr'. This may happen for a variety of reasons, such as reverse DNS misconfiguration. This subclass fixes that problem.""" def server_bind(self): """Override 'server_bind' to store the server name.""" # The problem occurs when an empty host name is specified as the # local address to which the socket binds. Specifying an empty # host name causes the socket to bind to 'INADDR_ANY', which # indicates that the socket should be bound to all interfaces. # # If the socket is bound to 'INADDR_ANY', 'gethostname' returns # '0.0.0.0'. In this case, 'BaseHTTPServer' tries unhelpfully # to obtain a host name to associate with the socket by calling # 'gethostname' and then 'gethostbyaddr' on the result. This # will raise a socket error if reverse lookup on the (primary) # host address fails. So, we use our own method to retrieve the # local host name, which fails more gracefully under this # circumstance. SocketServer.TCPServer.server_bind(self) host, port = self.socket.getsockname() # Use the primary host name if we're bound to all interfaces. # This is a bit misleading, because the primary host name may # not be bound to all interfaces. if not host or host == '0.0.0.0': host = socket.gethostname() # Try the broken 'BaseHTTPServer' implementation. try: hostname, hostnames, hostaddrs = socket.gethostbyaddr(host) if '.' not in hostname: for host in hostnames: if '.' in host: hostname = host break except socket.error: # If it bombs, use our more lenient method. hostname = qm.platform.get_host_name() self.server_name = hostname self.server_port = port class WebServer(HTTPServer): """A web server that serves ordinary files and dynamic content. To configure the server to serve ordinary files, register the directories containing those files with 'RegisterPathTranslations'. An arbitrary number of directories may be specified, and all files in each directory and under it are made available. To congifure the server to serve dynamic content, register dynamic URLs with 'RegisterScript'. A request matching the URL exactly will cause the server to invoke the provided function. The web server resolves request URLs in a two-step process. 1. The server checks if the URL matches exactly a script URL. If a match is found, the corresponding function is invoked, and its return value is sent to the client. 2. The server checks whether any registered path translation is a prefix of the reqest URL. If it is, the path is translated into a file system path, and the corresponding file is returned. The server also provides a rudimentary manual caching mechanism for generated pages. The application may insert a generated page into the page cache, if it is expected not to change. The application can use this mechanism: - to supress duplicate generation of the same page, - or to pre-generate a page that may be requested later. This is particularly handy if generating the page requires state information that would be difficult to reconstruct later. Pages may be shared across sessions, or may be specific to a particular session.""" def __init__(self, port, address="", log_file=sys.stderr): """Create a new web server. 'port' -- The port on which to accept connections. If 'port' is '0', then any port will do. 'address' -- The local address to which to bind. An empty string means bind to all local addresses. 'log_file' -- A file object to which to write log messages. If it's 'None', no logging. The server is not started until the 'Bind' and 'Run' methods are invoked.""" self.__port = port self.__address = address self.__log_file = log_file self.__scripts = {} self.__translations = {} self.__shutdown_requested = 0 self.RegisterScript("/problems.html", self._HandleProblems) self.RegisterScript("/", self._HandleRoot) # Register the common JavaScript. self.RegisterPathTranslation( "/common.js", qm.get_share_directory("web", "common.js")) self.__cache_dir = temporary_directory.TemporaryDirectory() self.__cache_path = self.__cache_dir.GetPath() os.mkdir(os.path.join(self.__cache_path, "sessions"), 0700) # Create a temporary attachment store to process attachment data # uploads. self.__temporary_store = qm.attachment.TemporaryAttachmentStore() self.RegisterScript(qm.fields.AttachmentField.upload_url, self.__temporary_store.HandleUploadRequest) # Don't call the base class __init__ here, since we don't want # to create the web server just yet. Instead, we'll call it # when it's time to run the server. def RegisterScript(self, script_path, script): """Register a dynamic URL. 'script_path' -- The URL for this script. A request must match this path exactly. 'script' -- A callable to invoke to generate the page content. If you register web_server.RegisterScript('/cgi-bin/myscript', make_page) then the URL 'http://my.server.com/cgi-bin/myscript' will respond with the output of calling 'make_page'. The script is passed a single argument, a 'WebRequest' instance. It returns the HTML source, as a string, of the page it generates. If it returns a tuple instead, the first element is taken to be a MIME type and the second is the data. The script may instead raise an 'HttpRedirect' instance, indicating an HTTP redirect response should be sent to the client.""" self.__scripts[script_path] = script def RegisterPathTranslation(self, url_path, file_path): """Register a path translation. 'url_path' -- The path in URL-space to map from. URLs of which 'url_path' is a prefix can be translated. 'file_path' -- The file system path corresponding to 'url_path'. For example, if you register web_server.RegisterPathTranslation('/images', '/path/to/pictures') the URL 'http://my.server.com/images/big/tree.gif' will be mapped to the file path '/path/to/pictures/big/tree.gif'.""" self.__translations[url_path] = file_path def IsScript(self, request): """Return a true value if 'request' corresponds to a script.""" return self.__scripts.has_key(request.GetUrl()) def ProcessScript(self, request): """Process 'request' as a script. 'request' -- A 'WebRequest' object. returns -- The output of the script.""" return self.__scripts[request.GetUrl()](request) def TranslateRequest(self, request): """Translate the URL in 'request' to a file system path. 'request' -- A 'WebRequest' object. returns -- A path to the corresponding file, or 'None' if the request URL didn't match any translations.""" path = request.GetUrl() # Loop over translations. for url_path, file_path in self.__translations.items(): # Is this translation a prefix of the URL? if path[:len(url_path)] == url_path: # Yes. First cut off the prefix that matched. sub_path = path[len(url_path):] # Make sure what's left doesn't look like an absolute path. if os.path.isabs(sub_path): sub_path = sub_path[1:] # Construct the file system path. if sub_path: file_path = os.path.join(file_path, sub_path) return file_path # No match was found. return None def Bind(self): """Bind the server to the specified address and port. Does not start serving.""" # Initialize the base class here. This binds the server # socket. try: # Base class initialization. Unfortunately, the base # class's initializer function (actually, its own base # class's initializer function, 'TCPServer.__init__') # doesn't provide a way to set options on the server socket # after it's created but before it's bound. # # If the SO_REUSEADDR option is not set before the socket is # bound, the bind operation will fail if there is alreay a # socket on the same port in the TIME_WAIT state. This # happens most frequently if a server is terminated and then # promptly restarted on the same port. Eventually, the # socket is cleaned up and the port number is available # again, but it's a big nuisance. The SO_REUSEADDR option # allows the new socket to be bound to the same port # immediately. # # So that we can insert the call to 'setsockopt' between the # socket creation and bind, we duplicate the body of # 'TCPServer.__init__' here and add the call. self.RequestHandlerClass = WebRequestHandler self.socket = socket.socket(self.address_family, self.socket_type) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server_address = (self.__address, self.__port) self.server_bind() self.server_activate() except socket.error, error: error_number, message = error if error_number == errno.EADDRINUSE: # The specified address/port is already in use. if self.__address == "": address = "port %d" % self.__port else: address = "%s:%d" % (self.__address, self.__port) raise AddressInUseError, address elif error_number == errno.EACCES: # Permission denied. raise PrivilegedPortError, "port %d" % self.__port else: # Propagate other exceptions. raise def Run(self): """Start the web server. preconditions -- The server must be bound.""" while not self.__shutdown_requested: self.handle_request() def RequestShutdown(self): """Shut the server down after processing the current request.""" self.__shutdown_requested = 1 def LogMessage(self, message): """Log a message.""" if self.__log_file is not None: self.__log_file.write(message) self.__log_file.flush() def GetServerAddress(self): """Return the host address on which this server is running. returns -- A pair '(hostname, port)'.""" return (self.server_name, self.server_port) def GetTemporaryAttachmentStore(self): """Return the 'AttachmentStore' used for new 'Attachment's. returns -- The 'AttachmentStore' used for new 'Attachment's.""" return self.__temporary_store def MakeButtonForCachedPopup(self, label, html_text, request=None, window_width=480, window_height=240): """Construct a button for displaying a cached popup page. 'label' -- The button label. 'html_text' -- The HTML source for the popup page. 'window_width' -- The width, in pixels, of the popup window. 'window_height' -- The height, in pixels, of the popup window. returns -- HTML source for the button. The button must be placed within a form element.""" # Place the page in the page cache. if request is None: session_id = None else: session_id = request.GetSessionId() page_url = self.CachePage(html_text, session_id).AsUrl() return make_button_for_popup(label, page_url, window_width, window_height) def MakeConfirmationDialog(self, message, url): """Generate JavaScript for a confirmation dialog box. 'url' -- The location in the main browser window is set to the URL if the user confirms the action. See 'make_popup_dialog_script' for a description of 'function_name' and 'message' and information on how to use the return value.""" # If the user clicks the "Yes" button, advance the main browser # page. open_script = "window.opener.document.location = %s;" \ % make_javascript_string(url) # Two buttons: "Yes" and "No". "No" doesn't do anything. buttons = [ ( "Yes", open_script ), ( "No", None ), ] return self.MakePopupDialog(message, buttons, title="Confirm") def MakePopupDialog(self, message, buttons, title=""): """Generate JavaScript to show a popup dialog box. The popup dialog box displays a message and one or more buttons. Each button can have a JavaScript statement (or statements) associated with it; if the button is clicked, the statement is invoked. After any button is clicked, the popup window is closed as well. 'message' -- HTML source of the message to display in the popup window. 'buttons' -- A sequence of button specifications. Each is a pair '(caption, script)'. 'caption' is the button caption. 'script' is the JavaScript statement to invoke when the button is clicked, or 'None'. 'title' -- The popup window title. returns -- JavaScript statements to show the dialog box, suiteable for use as an event handler.""" # Construct the popup page. page = make_popup_page(message, buttons, title) page_url = self.CachePage(page).AsUrl() # Construct the JavaScript variable and function. return "window.open('%s', 'popup', 'width=480,height=200,resizable')" \ % page_url def CachePage(self, page_text, session_id=None): """Cache an HTML page. 'page_text' -- The text of the page. 'session_id' -- The session ID for this page, or 'None'. returns -- A 'WebRequest' object with which the cached page can be retrieved later. If 'session_id' is 'None', the page is placed in the global page cache. Otherwise, it is placed in the session page cache for that session.""" if session_id is None: # No path was specified. Place the file in the top directory. dir_path = self.__cache_path script_name = _page_cache_name else: # A session was specified. Put the file in a subdirectory named # after the session. dir_path = os.path.join(self.__cache_path, "sessions", session_id) script_name = _session_cache_name # Create that directory if it doesn't exist. if not os.path.isdir(dir_path): os.mkdir(dir_path, 0700) # Generate a name for the page. global _counter page_name = str(_counter) _counter = _counter + 1 # Write it. page_file_name = os.path.join(dir_path, page_name) page_file = open(page_file_name, "w", 0600) page_file.write(page_text) page_file.close() # Return a request for this page. request = WebRequest(script_name, page=page_name) if session_id is not None: request.SetSessionId(session_id) return request def GetCachedPage(self, request, session_id=None): """Retrieve a page from the page cache. 'request' -- The URL requesting the page from the cache. 'session_id' -- The session ID for the request, or 'None'. returns -- The cached page, or a placeholder page if the page was not found in the cache. If 'session_id' is 'None', the page is retrieved from the global page cache. Otherwise, it is retrieved from the session page cache for that session.""" page_file_name = self.__GetPathForCachedPage(request, session_id) if os.path.isfile(page_file_name): # Return the page. return open(page_file_name, "r").read() else: # Oops, no such page. Generate a placeholder. return """

Cache Error

You have requested a page that no longer is in the server's cache. The server may have been restarted, or the page may have expired. Please start over.

""" % url def __GetPathForCachedPage(self, request, session_id): """Return the path for a cached page. 'request' -- The URL requesting the page from the cache. 'session_id' -- The session ID for the request, or 'None'.""" if session_id is None: dir_path = self.__cache_path else: # Construct the path to the directory containing pages in the # cache for 'session_id'. dir_path = os.path.join(self.__cache_path, "sessions", session_id) # Construct the path to the file containing the page. page_name = request["page"] return os.path.join(dir_path, page_name) def HandleNoSessionError(self, request, message): """Handler when session is absent.""" # There's no session specified in this request. Try to # create a session for the default user. try: user_id = user.authenticator.AuthenticateDefaultUser() except user.AuthenticationError: # Couldn't get a default user session, so bail. return generate_login_form(request, message) # Authenticating the default user succeeded. Create an implicit # session with the default user ID. session = Session(request, user_id) # Redirect to the same page but using the new session ID. request.SetSessionId(session.GetId()) raise HttpRedirect(request) def _HandleProblems(self, request): """Handle internal errors.""" return DtmlPage.default_class("problems.dtml")(request) def _HandleRoot(self, request): """Handle the '/' URL.""" raise HttpRedirect, WebRequest("/static/index.html") def handle_error(self, request, client_address): """Handle an error gracefully.""" # The usual cause of an error is a broken pipe; the user # may have clicked on something else in the browser before # we have time to finish writing the response to the browser. # In that case, we will get EPIPE when trying to write to the # pipe. # # The default behavior (inherited from BaseHTTPServer) # is to print the traceback to the standard error, which is # definitely not the right behavior for QMTest. If there # are any errors for which we must take explicit action, # we will have to add logic to handle them here. return class WebRequest: """An object representing a request from the web server. A 'WebRequest' object behaves as a dictionary of key, value pairs representing query arguments, for instance query fields in a POST, or arguments encoded in a URL query string. It has some other methods as well.""" def __init__(self, script_url, base=None, keep_fields=False, **fields): """Create a new request object. 'script_url' -- The URL of the script that processes this query. 'base' -- A request object from which the session ID will be duplicated, or 'None'. 'fields' -- The query arguments.""" self.__url = script_url self.__fields = {} if base and keep_fields: self.__fields.update(base.__fields) self.__fields.update(fields) # Copy the session ID from the base. if base is not None: session = base.GetSessionId() if session is not None: self.SetSessionId(session) self.client_address = base.client_address def __str__(self): str = "WebRequest for %s\n" % self.__url for name, value in self.__fields.items(): str = str + "%s=%s\n" % (name, repr(value)) return str def GetUrl(self): """Return the URL of the script that processes this request.""" return self.__url def GetScriptName(self): """Return the name of the script that processes this request. The script name is the final element of the full URL path.""" return string.split(self.__url, "/")[-1] def SetSessionId(self, session_id): """Set the session ID for this request to 'session_id'.""" self[session_id_field] = session_id def GetSessionId(self): """Return the session ID for this request. returns -- A session ID, or 'None'.""" return self.get(session_id_field, None) def GetSession(self): """Return the session for this request. raises -- 'NoSessionError' if no session ID is specified in the request. raises -- 'InvalidSessionError' if the session ID specified in the request is invalid.""" session_id = self.GetSessionId() if session_id is None: raise NoSessionError, qm.error("session required") else: return get_session(self, session_id) def AsUrl(self, last_argument=None): """Return the URL representation of this request. 'fields_at_end' -- If not 'None', the name of the URL query arguments that should be placed last in the list of arugmnets (other than this, the order of query arguments is not defined).""" if len(self.keys()) == 0: # No query arguments; just use the script URL. return self.GetUrl() else: # Encode query arguments into the URL. return "%s?%s" % (self.GetUrl(), urllib.urlencode(self)) def AsForm(self, method="get", name=None): """Return an opening form tag for this request. 'method' -- The HTML method to use for the form, either "get" or "post". 'name' -- A name for the form, or 'None'. returns -- An opening form tag for the request, plus hidden input elements for arguments to the request. The caller must add additional inputs, the submit input, and close the form tag.""" if name is not None: name_attribute = 'name="%s"' % name else: name_attribute = '' # Generate the form tag. if method == "get": result = '
\n' \ % (self.GetUrl(), name_attribute) elif method == "post": result = '''\n''' \ % (name_attribute, self.GetUrl()) else: raise ValueError, "unknown method %s" % method # Add hidden inputs for the request arguments. for name, value in self.items(): result = result \ + '\n' \ % (name, value) return result # Methods to emulate a mapping. def __getitem__(self, key): return self.__fields[key] def __setitem__(self, key, value): self.__fields[key] = value def __delitem__(self, key): del self.__fields[key] def get(self, key, default=None): return self.__fields.get(key, default) def keys(self): return self.__fields.keys() def has_key(self, key): return self.__fields.has_key(key) def items(self): return self.__fields.items() def copy(self, url=None, **fields): """Return a duplicate of this request. 'url' -- The URL for the request copy. If 'None', use the URL of the source. '**fields' -- Additional fields to set in the copy.""" # Copy the URL unless another was specified. if url is None: url = self.__url # Copy fields, and update with any that were specified # additionally. new_fields = self.__fields.copy() new_fields.update(fields) # Make the request. new_request = apply(WebRequest, (url, ), new_fields) # Copy the client address, if present. if hasattr(self, "client_address"): new_request.client_address = self.client_address return new_request class CGIWebRequest: """A 'WebRequest' object initialized from the CGI environment.""" def __init__(self): """Create a new request from the current CGI environment. preconditions -- The CGI environment (environment variables etc.) must be in place.""" assert os.environ.has_key("GATEWAY_INTERFACE") assert os.environ["GATEWAY_INTERFACE"][:3] == "CGI" self.__fields = cgi.FieldStorage() def GetUrl(self): return os.environ["SCRIPT_NAME"] def __getitem__(self, key): return self.__fields[key].value def keys(self): return self.__fields.keys() def has_key(self, key): return self.__fields.has_key(key) def copy(self): """Return a copy of the request. The copy isn't tied to the CGI environment, so it can be modified safely.""" fields = {} for key in self.keys(): fields[key] = self[key] return apply(WebRequest, (self.GetUrl(), ), fields) def _create_session_id(): # Seed the random number generator with the system time. random.seed() try: # hashlib is available since Python 2.5 import hashlib md5 = hashlib.md5() md5.update("%f" % random.random()) digest = md5.digest() except: # fall back to md5 on older Python versions import md5 # FIXME: Security: Is this OK? digest = md5.new("%f" % random.random()).digest() # Convert the digest, which is a 16-character string, # to a sequence hexadecimal bytes. digest = [hex(ord(c))[2:] for c in digest] # Convert it to a 32-character string. return ''.join(digest) class Session: """A persistent user session. A 'Session' object represents an ongoing user interaction with the web server.""" def __init__(self, request, user_id, expiration_timeout=21600): """Create a new session. 'request' -- A 'WebRequest' object in response to which this session is created. 'user_id' -- The ID of the user owning the session. 'expiration_timeout -- The expiration time, in seconds. If a session is not accessed for this duration, it is expired and no longer usable.""" self.__user_id = user_id self.__expiration_timeout = expiration_timeout # Extract the client's IP address from the request. self.__client_address = request.client_address self.__id = _create_session_id() self.Touch() # Record ourselves in the sessions map. sessions[self.__id] = self def Touch(self): """Update the last access time on the session to now.""" self.__last_access_time = time.time() def GetId(self): """Return the session ID.""" return self.__id def GetUserId(self): """Return the ID of the user who owns this session.""" return self.__user_id def GetUser(self): """Return the user record for the owning user. returns -- A 'qm.user.User' object.""" return user.database[self.__user_id] def IsDefaultUser(self): """Return true if the owning user is the default user.""" return self.GetUserId() == user.database.GetDefaultUserId() def IsExpired(self): """Return true if this session has expired.""" age = time.time() - self.__last_access_time return age > self.__expiration_timeout def Validate(self, request): """Make sure the session is OK for a request. 'request' -- A 'WebRequest' object. raises -- 'InvalidSessionError' if the session is invalid for the request.""" # Make sure the client IP address in the request matches that # for this session. if self.__client_address != request.client_address: raise InvalidSessionError, qm.error("session wrong IP") # Make sure the session hasn't expired. if self.IsExpired(): raise InvalidSessionError, qm.error("session expired") ######################################################################## # functions ######################################################################## def parse_url_query(url): """Parse a URL-encoded query. This function parses query strings encoded in URLs, such as '/script.cgi?key1=val1&key2=val2'. For this example, it would return '("/script.cgi", {"key1" : "val1", "key2" : "val2"})' 'url' -- The URL to parse. returns -- A pair containing the the base script path and a mapping of query field names to values.""" # Check if the script path is a URL-encoded query. if "?" in url: # Yes. Everything up to the question mark is the script # path; stuff after that is the query string. script_url, query_string = string.split(url, "?", 1) # Parse the query string. fields = cgi.parse_qs(query_string) # We only handle one instance of each key in the query. # 'parse_qs' produces a list of values for each key; check # that each list contains only one item, and replace the # list with that item. for key, value_list in fields.items(): if len(value_list) != 1: # Tell the client that we don't like this query. print "WARNING: Multiple values in query." fields[key] = value_list[0] else: # No, it's just an ordinary URL. script_url = url fields = {} script_url = urllib.unquote(script_url) return (script_url, fields) def http_return_html(html_text, stream=sys.stdout): """Generate an HTTP response consisting of HTML text. 'html_text' -- The HTML souce text to return. 'stream' -- The stream to write the response, by default 'sys.stdout.'.""" stream.write("Content-type: text/html\n\n") stream.write(html_text) def http_return_exception(exc_info=None, stream=sys.stdout): """Generate an HTTP response for an exception. 'exc_info' -- A three-element tuple containing exception info, of the form '(type, value, traceback)'. If 'None', use the exception currently being handled. 'stream' -- The stream to write the response, by default 'sys.stdout.'.""" if exc_info == None: exc_info = sys.exc_info() stream.write("Content-type: text/html\n\n"); stream.write(format_exception(exc_info)) def format_exception(exc_info): """Format an exception as HTML. 'exc_info' -- A three-element tuple containing exception info, of the form '(type, value, traceback)'. returns -- A string containing a complete HTML file displaying the exception.""" # Break up the exection info tuple. type, value, trace = exc_info # Format the traceback, with a newline separating elements. traceback_listing = string.join(traceback.format_tb(trace), "\n") # Construct a page info object to generate an exception page. page = DtmlPage.default_class( "exception.dtml", exception_type=type, exception_value=value, traceback_listing=traceback_listing) # Generate the page. return page() def escape(text): """Escape special characters in 'text' for formatting as HTML.""" return structured_text.escape_html_entities(text) # A regular expression that matches anything that looks like an entity. __entity_regex = re.compile("&(\w+);") # A function that returns the replacement for an entity matched by the # above expression. def __replacement_for_entity(match): entity = match.group(1) try: return htmlentitydefs.entitydefs[entity] except KeyError: return "&%s;" % entity def unescape(text): """Undo 'escape' by replacing entities with ordinary characters.""" return __entity_regex.sub(__replacement_for_entity, text) def format_structured_text(text): """Render 'text' as HTML.""" if text == "": # In case the text is the only contents of a table cell -- in # which case an empty string will produce undesirable visual # effects -- return a single space anyway. return " " else: return structured_text.to_html(text) def make_url(script_name, base_request=None, **fields): """Create a request and return a URL for it. 'script_name' -- The script name for the request. 'base_request' -- If not 'None', the base request for the generated request. 'fields' -- Additional fields to include in the request.""" request = apply(WebRequest, (script_name, base_request), fields) return request.AsUrl() def make_button_for_request(title, request, css_class=None): """Generate HTML for a button. Note that the caller is responsible for making sure the resulting button is placed within a form element. 'title' -- The button label. 'request' -- A 'WebRequest' object to be invoked when the button is clicked. 'css_class' -- The CSS class to use for the button, or 'None'.""" return make_button_for_url(title, request.AsUrl(), css_class) def make_button_for_url(title, url, css_class=None): """Generate HTML for a button. Note that the caller is responsible for making sure the resulting button is placed within a form element. 'title' -- The button label. 'url' -- The URL to load when the button is clicked.. 'css_class' -- The CSS class to use for the button, or 'None'.""" if css_class is None: class_attribute = "" else: class_attribute = 'class="%s"' % css_class return ''' ''' % (class_attribute, title, url) def get_session(request, session_id): """Retrieve the session corresponding to 'session_id'. 'request' -- A 'WebRequest' object for which to get the session. raises -- 'InvalidSessionError' if the session ID is invalid, or is invalid for this 'request'.""" # Now's as good a time as any to clean up expired sessions. __clean_up_expired_sessions() try: # Obtain the session for this ID. session = sessions[session_id] except KeyError: # No session for this ID (note that it may have expired). raise InvalidSessionError, qm.error("session invalid") # Make sure the session is valid for this request. session.Validate(request) # Update the last access time. session.Touch() return session def __clean_up_expired_sessions(): """Remove any sessions that are expired.""" for session_id, session in sessions.items(): if session.IsExpired(): del sessions[session_id] def handle_login(request, default_redirect_url="/"): """Handle a login request. Authenticate the login using the user name and password stored in the '_login_user_name' and '_login_password' request fields, respectively. If authentication succeeds, redirect to the URL stored in the '_redirect_url' request field by raising an 'HttpRedirect', passing all other request fields along as well. If '_redirect_url' is not specified in the request, the value of 'default_redirect_url' is used instead.""" # The URL of the page to which to redirect on successful login is # stored in the request. Extract it. redirect_url = request.get("_redirect_url", default_redirect_url) try: user_id = qm.user.authenticator.AuthenticateWebRequest(request) except qm.user.AuthenticationError: # Incorrect user name or password. Show the login form. message = qm.error("invalid login") redirect_request = WebRequest(redirect_url) return generate_login_form(redirect_request, message) except qm.user.AccountDisabledError: # Log in to a disabled account. Show the login form again. message = qm.error("disabled account") redirect_request = WebRequest(redirect_url) return generate_login_form(redirect_request, message) # Check if there is currently a session open for the same user ID. for session in sessions.values(): if session.GetUserId() == user_id: # Yup. There should be only one session at a time for any # given user. Close that session. del sessions[session.GetId()] session = Session(request, user_id) session_id = session.GetId() # Generate a new request for that URL. Copy other fields from the # old request. redirect_request = request.copy(redirect_url) # Sanitize the request by removing the user name, password, and # redirecting URL. del redirect_request["_login_user_name"] del redirect_request["_login_password"] if redirect_request.has_key("_redirect_url"): del redirect_request["_redirect_url"] # Add the ID of the new session to the request. redirect_request.SetSessionId(session_id) # Redirect the client to the URL for the redirected page. raise HttpRedirect, redirect_request def handle_logout(request, default_redirect_url="/"): """Handle a logout request. prerequisite -- 'request' must be in a valid session, which is ended. After ending the session, redirect to the URL specified by the '_redirect_url' field of 'request'. If '_redirect_url' is not specified in the request, the value of 'default_redirect_url' is used instead.""" # Delete the session. session_id = request.GetSessionId() del sessions[session_id] # Construct a redirecting URL. The target is contained in the # '_redirect_url' field. redirect_url = request.get("_redirect_url", default_redirect_url) redirect_request = request.copy(redirect_url) if redirect_request.has_key("_redirect_url"): del redirect_request["_redirect_url"] del redirect_request[session_id_field] # Redirect to the specified request. raise HttpRedirect, redirect_request def generate_error_page(request, error_text): """Generate a page to indicate a user error. 'request' -- The request that was being processed when the error was encountered. 'error_text' -- A description of the error, as structured text. returns -- The generated HTML source for the page.""" page = DtmlPage.default_class("error.dtml", error_text=error_text) return page(request) def generate_login_form(redirect_request, message=None): """Show a form for user login. 'message' -- If not 'None', a message to display to the user.""" page = DtmlPage.default_class( "login_form.dtml", message=message, default_user_id=qm.user.database.GetDefaultUserId()) return page(redirect_request) def make_set_control(form_name, field_name, add_page, select_name=None, initial_elements=[], request=None, rows=6, width=200, window_width=480, window_height=240, ordered=0): """Construct a control for representing a set of items. 'form_name' -- The name of form in which the control is included. 'field_name' -- The name of the input control that contains an encoded representation of the set's elements. See 'encode_set_control_contents' and 'decode_set_control_contents'. 'select_name' -- The name of the select control that displays the elements of the set. If 'None', a control name is generated automatically. 'add_page' -- The URL for a popup web page that is displayed in response to the "Add..." button. 'initial_elements' -- The initial elements of the set. 'rows' -- The number of rows for the select control. 'width' -- The width of the select control. 'window_width', 'window_height' -- The width and height of the popup window for adding a new element. 'ordered' -- If true, controls are included for specifying the order of elements in the set.""" # Generate a name for the select control if none was specified. if select_name is None: select_name = "_set_" + field_name # Construct the select control. select = '\n' # Construct the hidden control contianing the set's elements. Its # initial value is the encoding of the initial elements. initial_values = map(lambda x: x[1], initial_elements) initial_value = encode_set_control_contents(initial_values) contents = '' \ % (field_name, initial_value) buttons = [] # Construct the "Add..." button. buttons.append(make_button_for_popup("Add...", add_page, window_width, window_height)) # Construct the "Remove" button. buttons.append(''' ''' % (form_name, select_name, form_name, field_name)) if ordered: buttons.append(''' ''' % (form_name, select_name, form_name, field_name)) buttons.append(''' ''' % (form_name, select_name, form_name, field_name)) # Arrange everything in a table to control the layout. return contents + '''
%s   %s
''' % (select, string.join(buttons, "
")) def encode_set_control_contents(values): """Encode 'values' for a set control. 'values' -- A sequence of values of elements of the set. returns -- The encoded value for the control field.""" return string.join(values, ",") def decode_set_control_contents(content_string): """Decode the contents of a set control. 'content_string' -- The text of the form field containing the encoded set contents. returns -- A sequence of the values of the elements of the set.""" # Oddly, if the set is empty, there are sometimes spurious spaces in # field entry. This may be browser madness. Handle it specially. if string.strip(content_string) == "": return [] return string.split(content_string, ",") def make_properties_control(form_name, field_name, properties, select_name=None): """Construct a control for representing a set of properties. 'form_name' -- The name of form in which the control is included. 'field_name' -- The name of the input control that contains an encoded representation of the properties. See 'encode_properties' and 'decode_properties'. 'properties' -- A map from property names to values of the properties to include in the control initially. 'select_name' -- The name of the select control that displays the elements of the set. If 'None', a control name is generated automatically.""" # Generate a name for the select control if none was specified. if select_name is None: select_name = "_propsel_" + field_name name_control_name = "_propname_" + field_name value_control_name = "_propval_" + field_name add_change_button_name = "_propaddedit_" + field_name # Construct the select control. select = ''' \n' # Construct the hidden control contianing the set's elements. Its # initial value is the encoding of the initial elements. initial_value = encode_properties(properties) contents = '' \ % (field_name, initial_value) # Construct a control for the property name. name_control = \ '''''' % (name_control_name, form_name, add_change_button_name) # Construct a control for the property value. value_control = '' \ % value_control_name vars = { 'form' : form_name, 'button' : add_change_button_name, 'select' : select_name, 'field' : field_name, 'name' : name_control_name, 'value' : value_control_name } # Construct the "Change" button. When it's clicked, call # 'property_update', passing the select control and the hidden # control whose value should be updated with the new encoded # property list. add_change_button = \ '''''' % vars # Construct the "Remove" button. remove_button = \ '''''' % vars # Arrange everything in a table to control the layout. return contents + '''
%s   %s
Name:  %s   %s
Value:  %s    
''' % (select, remove_button, name_control, add_change_button, value_control) def encode_properties(properties): """Construct a URL-encoded representation of a set of properties. 'properties' -- A map from property names to values. Names must be URL-safe strings. Values are arbitrary strings. returns -- A URL-encoded string representation of 'properties'. This function is the inverse of 'decode_properties'.""" # Construct a list of property assignment strings. The RHS is # URL-quoted. result = map(lambda p: "%s=%s" % (p[0], urllib.quote_plus(p[1])), properties.items()) # Join them into a comma-delimited list. return string.join(result, ",") def decode_properties(properties): """Decode a URL-encoded representation of a set of properties. 'properties' -- A string containing URL-encoded properties. returns -- A map from names to values. This function is the inverse of 'encode_properties'.""" properties = string.strip(properties) # Empty? if properties == "": return {} # The string is a comma-delimited list. Split it up. properties = string.split(properties, ",") # Convert to a map, processing each item. result = {} for assignment in properties: # Each element is a "name=value" assignment. Split it up. name, value = string.split(assignment, "=") # The value is URL-quoted. Unquote it. value = urllib.unquote_plus(value) # Set it in the map. result[name] = value return result def make_javascript_string(text): """Return 'text' represented as a JavaScript string literal.""" text = string.replace(text, "\\", r"\\") text = string.replace(text, "'", r"\'") text = string.replace(text, "\"", r'\"') text = string.replace(text, "\n", r"\n") # Escape less-than signs so browsers don't look for HTML tags # inside the literal. text = string.replace(text, "<", r"\074") return "'" + text + "'" def make_help_link(help_text_tag, label="Help", **substitutions): """Make a link to pop up help text. 'help_text_tag' -- A message tag for the help diagnostic. 'label' -- The help link label. 'substitutions' -- Substitutions to the help diagnostic.""" # Construct the help text. help_text = apply(diagnostic.get_help_set().Generate, (help_text_tag, "help", None), substitutions) # Convert it to HTML. help_text = qm.structured_text.to_html(help_text) # Make the link. return make_help_link_html(help_text, label) def make_help_link_html(help_text, label="Help"): """Make a link to pop up help text. 'help_text' -- HTML source for the help text. 'label' -- The help link label.""" global _counter # Wrap the help text in a complete HTML page. help_page = DtmlPage("help.dtml", help_text=help_text) # Embed the page in a JavaScript string literal. help_page_string = make_javascript_string(help_page()) # Construct the name for the JavaScript variable which will hold the # help page. help_variable_name = "_help_text_%d" % _counter _counter = _counter + 1 # Construct the link. return \ '''%s %s var %s = %s; %s ''' % (help_variable_name, label, help_page.GenerateStartScript(), help_variable_name, help_page_string, help_page.GenerateEndScript()) def make_popup_page(message, buttons, title=""): """Generate a popup dialog box page. See 'make_popup_dialog_script' for an explanation of the parameters.""" page = \ ''' %s
%s
''' % (title, message) # Generate the buttons. for caption, script in buttons: page = page + ''' ''' # End the page. page = page + '''
''' return page def make_choose_control(field_name, included_label, included_items, excluded_label, excluded_items, item_to_text=str, item_to_value=str, ordered=0): """Construct HTML controls for selecting a subset. The user is presented with two list boxes next to each other. The box on the left lists items included in the subset. The box on the right lists items excluded from the subset but available for inclusion. Between the boxes are buttons for adding and removing items from the subset. If 'ordered' is true, buttons are also shown for reordering items in the included list. 'field_name' -- The name of an HTML hidden form field that will contain an encoding of the items included in the subset. The encoding consists of the values corresponding to included items, in a comma-separated list. 'included_label' -- HTML source for the label for the left box, which displays the included items. 'included_items' -- Items initially included in the subset. This is a sequence of arbitrary objects or values. 'excluded_label' -- HTML source for the label for the right box, which displays the items available for inclusion but not currently included. 'excluded_items' -- Items not initially included but available for inclusion. This is a sequence of arbitrary objects or values. 'item_to_text' -- A function that produces a user-visible text description of an item. 'item_to_value' -- A function that produces a value for an item, used as the value for an HTML option object. 'ordered' -- If true, additional controls are displayed to allow the user to manipulate the order of items in the included set. returns -- HTML source for the items. Must be placed in a form.""" # We'll construct an array of buttons. Each element is an HTML # input control. buttons = [] # Construct the encoding for the items initially included. initial_value = string.join(map(item_to_value, included_items), ",") # The hidden control that will contain the encoded representation of # the included items. hidden_control = '' \ % (field_name, initial_value) # Construct names for the two select controls. included_select_name = "_inc_" + field_name excluded_select_name = "_exc_" + field_name # The select control for included items. When the user selects an # item in this list, deselect the selected item in the excluded # list, if any. included_select = ''' \n' # The select control for excluded items. When the user selects an # item in this list, deselect the selected item in the included # list, if any. excluded_select = ''' \n' # The Add button. button = ''' ''' % (excluded_select_name, included_select_name, field_name, included_select_name) buttons.append(button) # The Remove button. button = '''    ''' % (included_select_name, excluded_select_name, field_name, included_select_name) buttons.append(button) if ordered: # The Move Up button. button = ''' ''' % (included_select_name, field_name, included_select_name) buttons.append(button) # The Move Down button. button = ''' ''' % (included_select_name, field_name, included_select_name) buttons.append(button) # Arrange everything properly. buttons = string.join(buttons, "\n
\n") return ''' %(hidden_control)s
%(included_label)s:
%(included_select)s
%(buttons)s %(excluded_label)s:
%(excluded_select)s
''' % locals() def make_button_for_popup(label, url, window_width=480, window_height=240): """Construct a button for displaying a popup page. 'label' -- The button label. 'url' -- The URL to display in the popup page. returns -- HTML source for the button. The button must be placed within a form element.""" # Construct arguments for 'Window.open'. window_args = "resizable,width=%d,height=%s" \ % (window_width, window_height) # Generate it. return """ """ % locals() def format_color(red, green, blue): """Format an RGB color value for HTML. 'red', 'green', 'blue' -- Color values for respective channels, between 0.0 and 1.0. Values outside this range are truncated to this range.""" # Manual loop unrolling, for efficiency. red = int(256 * red) if red < 0: red = 0 if red > 255: red = 255 green = int(256 * green) if green < 0: green = 0 if green > 255: green = 255 blue = int(256 * blue) if blue < 0: blue = 0 if blue > 255: blue = 255 return "#%02x%02x%02x" % (red, green, blue) def javascript_escape(text): """Equivalent to the JavaScript 'escape' built-in function.""" text = urllib.quote(text) text = string.replace(text, ",", "%2C") return text def javascript_unescape(text): """Equivalent to the JavaScript 'unescape' built-in function.""" return urllib.unquote(text) def make_submit_button(title="OK"): """Generate HTML for a button to submit the current form. 'title' -- The button title.""" return ''' ''' % title ######################################################################## # variables ######################################################################## sessions = {} """A mapping from session IDs to 'Session' instances.""" _counter = 0 """A counter for generating somewhat-unique names.""" _page_cache_name = "page-cache" """The URL prefix for the global page cache.""" _session_cache_name = "session-cache" """The URL prefix for the session page cache.""" ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/__init__.py0000664000076400007640000000220511107032237015110 0ustar stefanstefan######################################################################## # # File: __init__.py # Author: Alex Samuel # Date: 2000-12-20 # # Contents: # Initialization for module qm. # # Copyright (c) 2000 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.common import * from qm.diagnostic import error, warning, message from qm.config import version from qm.config import data_dir from qm.config import doc_dir from qm.config import extension_path # The prefix variable is only available after QMTest is built. # Compute it, if it isn't available. try: from qm.config import prefix except ImportError: import os prefix = os.path.join(os.path.dirname(__file__), os.path.pardir) version_info = tuple(version.split('.')) ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # End: qmtest-2.4.1/qm/extension.py0000664000076400007640000005703211107032237015375 0ustar stefanstefan######################################################################## # # File: extension.py # Author: Mark Mitchell # Date: 07/31/2002 # # Contents: # Extension # # Copyright (c) 2002, 2003 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## import os.path import qm from qm.fields import Field import StringIO import tokenize import xml ######################################################################## # Classes ######################################################################## class Extension(object): """A class derived from 'Extension' is a QM extension. A variety of different classes are derived from 'Extension'. All of these classes can be derived from by users to produce customized QM extensions. 'Extension' is an abstract class.""" class Type(type): def __init__(cls, name, bases, dict): """Generate an '_argument_dictionary' holding all the 'Field' objects. Then replace 'Field' objects by their values for convenient use inside the code.""" # List all base classes that are themselves of type Extension. # # 'Extension' isn't known at this point so all we can do to find # Extension base classes is test whether __metaclass__ is defined # and if so, whether it is a base class of the metaclass of cls. type = cls.__metaclass__ def is_extension(base): metaclass = getattr(base, '__metaclass__', None) return metaclass and issubclass(type, metaclass) hierarchy = [base for base in bases if is_extension(base)] parameters = {} for c in hierarchy: parameters.update(c._argument_dictionary) # Now set parameters from class variables of type 'Field'. for key, field in dict.iteritems(): if isinstance(field, Field): field.SetName(key) parameters[key] = field # For backward compatibility, inject all members of the # 'arguments' list into the dict, if it is indeed a list of fields. arguments = dict.get('arguments', []) if (type(arguments) is list and len(arguments) > 0 and isinstance(arguments[0], Field)): for field in arguments: # Only allow name collisions between arguments and # class variables if _allow_arg_names_matching_class_vars # evaluates to True. if (hasattr(cls, field.GetName()) and not cls._argument_dictionary.has_key(field.GetName()) and not cls._allow_arg_names_matching_class_vars): raise qm.common.QMException, \ qm.error("ext arg name matches class var", class_name = name, argument_name = field.GetName()) parameters[field.GetName()] = field setattr(cls, '_argument_dictionary', parameters) setattr(cls, '_argument_list', parameters.values()) # Finally set default values. for i in parameters: setattr(cls, i, parameters[i].GetDefaultValue()) __metaclass__ = Type arguments = [] """A list of the arguments to the extension class. Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument. Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.""" kind = None """A string giving kind of extension is implemented by the class. This field is used in an application-specific way; for example, QMTest has 'test' and 'target' extension classes.""" _argument_list = None """A list of all the 'Field's in this class. This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.""" _argument_dictionary = None """A map from argument names to 'Field' instances. A map from the names of arguments for this class to the corresponding 'Field'.""" _allow_arg_names_matching_class_vars = None """True if it is OK for fields to have the same name as class variables. If this variable is set to true, it is OK for the 'arguments' to contain a field whose name is the same as a class variable. That makes the 'default_value' handling for fields fail, and is generally confusing. This module no longer allows such classes, unless this variable is set to true. That permits legacy extension classes to continue working, while preventing new extension classes from making the same mistake.""" def __init__(self, **args): """Construct a new 'Extension'. 'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes. This method will place all of the arguments into this objects instance dictionary. Derived classes may override this method, but should call this method during their processing.""" # Make sure that all the arguments actually correspond to # 'Field's for this class. if __debug__: dictionary = get_class_arguments_as_dictionary(self.__class__) for a, v in args.items(): if not dictionary.has_key(a): raise AttributeError, a # Remember the arguments provided. self.__dict__.update(args) def __getattr__(self, name): # Perhaps a default value for a class argument should be used. field = get_class_arguments_as_dictionary(self.__class__).get(name) if field is None: raise AttributeError, name return field.GetDefaultValue() def GetClassName(self): """Return the name of the extension class. returns -- A string giving the name of this etension class.""" return get_extension_class_name(self.__class__) def GetExplicitArguments(self): """Return the arguments to this extension instance. returns -- A dictionary mapping argument names to their values. Computed arguments are ommitted from the dictionary.""" # Get all of the arguments. arguments = get_class_arguments_as_dictionary(self.__class__) # Determine which subset of the 'arguments' have been set # explicitly. explicit_arguments = {} for name, field in arguments.items(): # Do not record computed fields. if field.IsComputed(): continue if self.__dict__.has_key(name): explicit_arguments[name] = self.__dict__[name] return explicit_arguments def MakeDomElement(self, document, element = None): """Create a DOM node for 'self'. 'document' -- The DOM document that will contain the new element. 'element' -- If not 'None' the extension element to which items will be added. Otherwise, a new element will be created by this function. returns -- A new DOM element corresponding to an instance of the extension class. The caller is responsible for attaching it to the 'document'.""" return make_dom_element(self.__class__, self.GetExplicitArguments(), document, element) def MakeDomDocument(self): """Create a DOM document for 'self'. 'extension_class' -- A class derived from 'Extension'. 'arguments' -- The arguments to the extension class. returns -- A new DOM document corresponding to an instance of the extension class.""" document = qm.xmlutil.create_dom_document( public_id = "Extension", document_element_tag = "extension" ) self.MakeDomElement(document, document.documentElement) return document def Write(self, file): """Write an XML description of 'self' to a file. 'file' -- A file object to which the data should be written.""" document = self.MakeDomDocument() document.writexml(file) ######################################################################## # Functions ######################################################################## def get_class_arguments(extension_class): """Return the arguments associated with 'extension_class'. 'extension_class' -- A class derived from 'Extension'. returns -- A list of 'Field' objects containing all of the arguments in the class hierarchy.""" assert issubclass(extension_class, Extension) return extension_class._argument_list def get_class_arguments_as_dictionary(extension_class): """Return the arguments associated with 'extension_class'. 'extension_class' -- A class derived from 'Extension'. returns -- A dictionary mapping argument names to 'Field' objects. The dictionary contains all of the arguments in the class hierarchy.""" assert issubclass(extension_class, Extension) return extension_class._argument_dictionary def get_class_description(extension_class, brief=0): """Return a brief description of the extension class 'extension_class'. 'extension_class' -- A class derived from 'Extension'. 'brief' -- If true, return a brief (one-line) description of the extension class. returns -- A structured text description of 'extension_class'.""" assert issubclass(extension_class, Extension) # Extract the class's doc string. doc_string = extension_class.__doc__ if doc_string is not None: if brief: doc_string = qm.structured_text.get_first(doc_string) return doc_string else: return " " def get_extension_class_name(extension_class): """Return the name of 'extension_class'. 'extension_class' -- A class derived from 'Extension'. returns -- The name of 'extension_class'. This is the name that is used when users refer to the class.""" assert issubclass(extension_class, Extension) module = extension_class.__module__.split(".")[-1] return module + "." + extension_class.__name__ def validate_arguments(extension_class, arguments): """Validate the 'arguments' to the 'extension_class'. 'extension_class' -- A class derived from 'Extension'. 'arguments' -- A dictionary mapping argument names (strings) to values (strings). returns -- A dictionary mapping 'Field's to values. Check that each of the 'arguments' is a valid argument to 'extension_class'. If so, the argumets are converted as required by the 'Field', and the dictionary returned contains the converted values. Otherwise, an exception is raised.""" assert issubclass(extension_class, Extension) # We have not converted any arguments yet. converted_arguments = {} # Check that there are no arguments that do not apply to this # class. class_arguments = get_class_arguments_as_dictionary(extension_class) for name, value in arguments.items(): field = class_arguments.get(name) if not field: raise qm.QMException, \ qm.error("unexpected extension argument", name = name, class_name \ = get_extension_class_name(extension_class)) if field.IsComputed(): raise qm.QMException, \ qm.error("value provided for computed field", name = name, class_name \ = get_extension_class_name(extension_class)) converted_arguments[name] = field.ParseTextValue(value) return converted_arguments def make_dom_element(extension_class, arguments, document, element = None): """Create a DOM node for an instance of 'extension_class'. 'extension_class' -- A class derived from 'Extension'. 'arguments' -- The arguments to the extension class. 'document' -- The DOM document that will contain the new element. 'element' -- If not 'None' the extension element to which items will be added. Otherwise, a new element will be created by this function. returns -- A new DOM element corresponding to an instance of the extension class. The caller is responsible for attaching it to the 'document'.""" # Get the dictionary of 'Field's for this extension class. field_dictionary = get_class_arguments_as_dictionary(extension_class) # Create the element. if element: extension_element = element else: extension_element = document.createElement("extension") # Create an attribute describing the kind of extension. if extension_class.kind: extension_element.setAttribute("kind", extension_class.kind) # Create an attribute naming the extension class. extension_element.setAttribute("class", get_extension_class_name(extension_class)) # Create an element for each of the arguments. for argument_name, value in arguments.items(): # Skip computed arguments. field = field_dictionary[argument_name] if field.IsComputed(): continue # Create a node for the argument. argument_element = document.createElement("argument") # Store the name of the field. argument_element.setAttribute("name", argument_name) # Store the value. argument_element.appendChild(field.MakeDomNodeForValue(value, document)) # Add the attribute node to the target. extension_element.appendChild(argument_element) return extension_element def make_dom_document(extension_class, arguments): """Create a DOM document for an instance of 'extension_class'. 'extension_class' -- A class derived from 'Extension'. 'arguments' -- The arguments to the extension class. returns -- A new DOM document corresponding to an instance of the extension class.""" document = qm.xmlutil.create_dom_document( public_id = "Extension", document_element_tag = "extension" ) make_dom_element(extension_class, arguments, document, document.documentElement) return document def write_extension_file(extension_class, arguments, file): """Write an XML description of an extension to 'file'. 'extension_class' -- A class derived from 'Extension'. 'arguments' -- A dictionary mapping argument names to values. 'file' -- A file object to which the data should be written.""" document = make_dom_document(extension_class, arguments) document.writexml(file) def parse_dom_element(element, class_loader, attachment_store = None): """Parse a DOM node representing an instance of 'Extension'. 'element' -- A DOM node, of the format created by 'make_dom_element'. 'class_loader' -- A callable. The callable will be passed the name of the extension class and must return the actual class object. 'attachment_store' -- The 'AttachmentStore' in which attachments can be found. returns -- A pair ('extension_class', 'arguments') containing the extension class (a class derived from 'Extension') and the arguments (a dictionary mapping names to values) stored in the 'element'.""" # Determine the name of the extension class. class_name = element.getAttribute("class") # DOM nodes created by earlier versions of QMTest encoded the # class name in a separate element, so look there for backwards # compatbility. if not class_name: class_elements = element.getElementsByTagName("class") if not class_elements: class_elements = element.getElementsByTagName("class-name") class_element = class_elements[0] class_name = qm.xmlutil.get_dom_text(class_element) # Load it. extension_class = class_loader(class_name) # Get the dictionary of 'Field's for this extension class. field_dictionary = get_class_arguments_as_dictionary(extension_class) # Collect the arguments to the extension class. arguments = {} for argument_element in element.getElementsByTagName("argument"): name = argument_element.getAttribute("name") # Find the corresponding 'Field'. field = field_dictionary[name] # Get the DOM node for the value. It is always a element. value_node \ = filter(lambda e: e.nodeType == xml.dom.Node.ELEMENT_NODE, argument_element.childNodes)[0] # Parse the value. value = field.GetValueFromDomNode(value_node, attachment_store) # Python does not allow keyword arguments to have Unicode # values, so we convert the name to an ordinary string. arguments[str(name)] = value return (extension_class, arguments) def read_extension_file(file, class_loader, attachment_store = None): """Parse a file describing an extension instance. 'file' -- A file-like object from which the extension instance will be read. 'class_loader' -- A callable. The callable will be passed the name of the extension class and must return the actual class object. 'attachment_store' -- The 'AttachmentStore' in which attachments can be found. returns -- A pair ('extension_class', 'arguments') containing the extension class (a class derived from 'Extension') and the arguments (a dictionary mapping names to values) stored in the 'element'.""" document = qm.xmlutil.load_xml(file) return parse_dom_element(document.documentElement, class_loader, attachment_store) def parse_descriptor(descriptor, class_loader, extension_loader = None): """Parse a descriptor representing an instance of 'Extension'. 'descriptor' -- A string representing an instance of 'Extension'. The 'descriptor' has the form 'class(arg1 = "val1", arg2 = "val2", ...)'. The arguments and the parentheses are optional. 'class_loader' -- A callable that, when passed the name of the extension class, will return the actual Python class object. 'extension_loader' -- A callable that loads an existing extension given the name of that extension and returns a tuple '(class, arguments)' where 'class' is a class derived from 'Extension'. If 'extension_loader' is 'None', or if the 'class' returned is 'None', then if a file exists named 'class', the extension is read from 'class' as XML. Any arguments returned by the extension loader or read from the file system are overridden by the arguments explicitly provided in the descriptor. returns -- A pair ('extension_class', 'arguments') containing the extension class (a class derived from 'Extension') and the arguments (a dictionary mapping names to values) stored in the 'element'. The 'arguments' will have already been processed by 'validate_arguments' by the time they are returned.""" # Look for the opening parenthesis. open_paren = descriptor.find('(') if open_paren == -1: # If there is no opening parenthesis, the descriptor is simply # the name of an extension class. class_name = descriptor else: # The class name is the part of the descriptor up to the # parenthesis. class_name = descriptor[:open_paren] # Load the extension, if it already exists. extension_class = None if extension_loader: extension = extension_loader(class_name) if extension: extension_class = extension.__class__ orig_arguments = extension.GetExplicitArguments() if not extension_class: if os.path.exists(class_name): extension_class, orig_arguments \ = read_extension_file(open(filename), class_loader) else: extension_class = class_loader(class_name) orig_arguments = {} arguments = {} # Parse the arguments. if open_paren != -1: # Create a file-like object for the remainder of the string. arguments_string = descriptor[open_paren:] s = StringIO.StringIO(arguments_string) # Use the Python tokenizer to process the remainder of the # string. g = tokenize.generate_tokens(s.readline) # Read the opening parenthesis. tok = g.next() assert tok[0] == tokenize.OP and tok[1] == "(" need_comma = 0 # Keep going until we find the closing parenthesis. while 1: tok = g.next() if tok[0] == tokenize.OP and tok[1] == ")": break # All arguments but the first must be separated by commas. if need_comma: if tok[0] != tokenize.OP or tok[1] != ",": raise qm.QMException, \ qm.error("invalid descriptor syntax", start = arguments_string[tok[2][1]:]) tok = g.next() # Read the argument name. if tok[0] != tokenize.NAME: raise qm.QMException, \ qm.error("invalid descriptor syntax", start = arguments_string[tok[2][1]:]) name = tok[1] # Read the '='. tok = g.next() if tok[0] != tokenize.OP or tok[1] != "=": raise qm.QMException, \ qm.error("invalid descriptor syntax", start = arguments_string[tok[2][1]:]) # Read the value. tok = g.next() if tok[0] != tokenize.STRING: raise qm.QMException, \ qm.error("invalid descriptor syntax", start = arguments_string[tok[2][1]:]) # The token string will have surrounding quotes. By # running it through "eval", we get at the underlying # value. value = eval(tok[1]) arguments[name] = value # The next argument must be preceded by a comma. need_comma = 1 # There shouldn't be anything left at this point. tok = g.next() if not tokenize.ISEOF(tok[0]): raise qm.QMException, \ qm.error("invalid descriptor syntax", start = arguments_string[tok[2][1]:]) # Process the arguments. arguments = validate_arguments(extension_class, arguments) # Use the explict arguments to override any specified in the file. orig_arguments.update(arguments) return (extension_class, orig_arguments) qmtest-2.4.1/qm/common.py0000664000076400007640000007055711107032237014660 0ustar stefanstefan######################################################################## # # File: common.py # Author: Alex Samuel # Date: 2000-12-20 # # Contents: # General-purpose classes and functions. # # Copyright (c) 2000, 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## from calendar import timegm import ConfigParser import imp import lock import os import os.path import qm import re import string import sys import tempfile import time import traceback import types import getpass import StringIO import htmllib import formatter if sys.platform != "win32": import fcntl ######################################################################## # program name ######################################################################## program_name = None """The name of the application program.""" ######################################################################## # exceptions ######################################################################## class QMException(Exception): """An exception generated directly by QM. All exceptions thrown by QM should be derived from this class.""" def __init__(self, message): """Construct a new 'QMException'. 'message' -- A string describing the cause of the message as structured text. If this exception is not handled, the 'message' will be displayed as an error message.""" Exception.__init__(self, message) class UserError(QMException): pass class PythonException(QMException): """A 'PythonException' is a wrapper around a Python exception. A 'PythonException' is a 'QMException' and, as such, can be processed by the QM error-handling routines. However, the raw Python exception which triggered this exception can be obtained by using the 'exc_type' and 'exc_value' attributes of this exception.""" def __init__(self, message, exc_type, exc_value): """Construct a new 'PythonException'. 'message' -- A string describing the cause of the message as structured text. If this exception is not handled, the 'message' will be displayed as an error message. 'exc_type' -- The type of the Python exception. 'exc_value' -- The value of the Python exception.""" QMException.__init__(self, message) self.exc_type = exc_type self.exc_value = exc_value ######################################################################## # classes ######################################################################## class RcConfiguration(ConfigParser.ConfigParser): """Interface object to QM configuration files. Configuration files are in the format parsed by the standard 'ConfigParser' module, namely 'win.ini'--style files.""" user_rc_file_name = ".qmrc" """The name of the user configuration file.""" def __init__(self): """Create a new configuration instance.""" ConfigParser.ConfigParser.__init__(self) if os.environ.has_key("HOME"): home_directory = os.environ["HOME"] rc_file = os.path.join(home_directory, self.user_rc_file_name) # Note that it's OK to call 'read' even if the file doesn't # exist. In that, case the parser simply will not # accumulate any data. self.read(rc_file) def Load(self, section): """Load configuration. 'section' -- The configuration section from which subsequent variables are loaded.""" self.__section = section def Get(self, option, default, section=None): """Retrieve a configuration variable. 'option' -- The name of the option to retrieve. 'default' -- The default value to return if the option is not found. 'section' -- The section from which to retrieve the option. 'None' indicates the section specified to the 'Load' method for this instance. precondition -- The RC configuration must be loaded.""" # Use the previously-specified default section, if one wasn't # specified explicitly. if section is None: section = self.__section try: # Try to get the requested option. return self.get(section, option) except ConfigParser.NoSectionError: # Couldn't find the section. return default except ConfigParser.NoOptionError: # Couldn't find the option. return default def GetOptions(self, section=None): """Return a sequence of options. 'section' -- The section for which to list options, or 'None' for the section specified to 'Load'. precondition -- The RC configuration must be loaded.""" # Use the previously-specified default section, if one wasn't # specified explicitly. if section is None: section = self.__section try: options = self.options(section) except ConfigParser.NoSectionError: # Couldn't find the section. return [] else: # 'ConfigParser' puts in a magic option '__name__', which is # the name of the section. Remove it. if "__name__" in options: options.remove("__name__") return options ######################################################################## # Functions ######################################################################## def get_lib_directory(*components): """Return the path to a file in the QM library directory.""" # This is a file in the top-level QM library directory, so we can # just return a path relative to ourselves. return os.path.join(os.path.dirname(__file__), *components) def get_share_directory(*components): """Return the path to a file in the QM data file directory.""" return os.path.join(qm.prefix, qm.data_dir, *components) def get_doc_directory(*components): """Return a path to a file in the QM documentation file directory.""" return os.path.join(qm.prefix, qm.doc_dir, *components) def format_exception(exc_info): """Format an exception as structured text. 'exc_info' -- A three-element tuple containing exception info, of the form '(type, value, traceback)'. returns -- A string containing a the formatted exception.""" # Break up the exection info tuple. type, value, trace = exc_info # Generate output. traceback_listing = format_traceback(exc_info) return "Exception '%s' : '%s'\n\n%s\n" % (type, value, traceback_listing) def format_traceback(exc_info): """Format an exception traceback as structured text. 'exc_info' -- A three-element tuple containing exception info, of the form '(type, value, traceback)'. returns -- A string containing a the formatted traceback.""" return string.join(traceback.format_tb(exc_info[2]), "\n") def convert_from_dos_text(text): """Replace CRLF with LF in 'text'.""" return string.replace(text, "\r\n", "\n") __load_module_lock = lock.RLock() """A lock used by load_module.""" def load_module(name, search_path=sys.path, load_path=sys.path): """Load a Python module. 'name' -- The fully-qualified name of the module to load, for instance 'package.subpackage.module'. 'search_path' -- A sequence of directories. These directories are searched to find the module. 'load_path' -- The setting of 'sys.path' when the module is loaded. returns -- A module object. raises -- 'ImportError' if the module cannot be found.""" # The implementation of this function follows the prescription in # the documentation for the standard Python 'imp' module. See also # the 'knee' package included unofficially in the standard Python # library. # In order to avoid getting incomplete modules, grab a lock here. # Use a recursive lock so that deadlock does not occur if the loaded # module loads more modules. __load_module_lock.acquire() try: # Is the module already loaded? module = sys.modules.get(name) if module: return module # The module may be in a package. Split the module path into # components. components = string.split(name, ".") if len(components) > 1: # The module is in a package. Construct the name of the # containing package. parent_package = string.join(components[:-1], ".") # Load the containing package. package = load_module(parent_package, search_path, load_path) # Look for the module in the parent package. search_path = package.__path__ else: # No containing package. package = None # The name of the module itself is the last component of the module # path. module_name = components[-1] # Locate the module. file, file_name, description = imp.find_module(module_name, search_path) # Find the module. try: # While loading the module, add 'path' to Python's module path, # so that if the module references other modules, e.g. in the # same directory, Python can find them. But remember the old # path so we can restore it afterwards. old_python_path = sys.path[:] sys.path = load_path + sys.path # Load the module. try: module = imp.load_module(name, file, file_name, description) except: # Don't leave a broken module object in sys.modules. if sys.modules.has_key(name): del sys.modules[name] raise # Restore the old path. sys.path = old_python_path # Loaded successfully. If it's contained in a package, put it # into that package's name space. if package is not None: setattr(package, module_name, module) return module finally: # Close the module file, if one was opened. if file is not None: file.close() finally: # Release the lock. __load_module_lock.release() def load_class(name, search_path = sys.path, load_path = sys.path): """Load a Python class. 'name' -- The fully-qualified (including package and module names) class name, for instance 'package.subpackage.module.MyClass'. The class must be at the top level of the module's namespace, i.e. not nested in another class. 'search_path' -- A sequence of directories. These directories are searched to find the module. 'load_path' -- The setting of 'sys.path' when the module is loaded. returns -- A class object. raises -- 'ImportError' if the module containing the class can't be imported, or if there is no class with the specified name in that module, or if 'name' doesn't correspond to a class.""" # Make sure the class name is fully-qualified. It must at least be # in a top-level module, so there should be at least one module path # separator. if not "." in name: raise QMException, \ "%s is not a fully-qualified class name" % name # Split the module path into components. components = string.split(name, ".") # Reconstruct the full path to the containing module. module_name = string.join(components[:-1], ".") # The last element is the name of the class. class_name = components[-1] # Load the containing module. module = load_module(module_name, search_path, load_path) # Extract the requested class. try: klass = module.__dict__[class_name] # Check to see the KLASS really is a class. Python 2.2's # "new-style" classes are not instances of types.ClassType so we # must check two conditions: one for old-style and one for # new-style classes. if (not isinstance(klass, types.ClassType) and not issubclass(klass, object)): # There's something by that name, but it's not a class raise QMException, "%s is not a class" % name return klass except KeyError: # There's no class with the requested name. raise QMException, \ "no class named %s in module %s" % (class_name, module_name) def split_path_fully(path): """Split 'path' into components. Uses 'os.path.split' recursively on the directory components of 'path' to separate all path components. 'path' -- The path to split. returns -- A list of path componets.""" dir, entry = os.path.split(path) if dir == "" or dir == os.sep: return [ entry ] else: return split_path_fully(dir) + [ entry ] def open_temporary_file_fd(suffix = ""): """Create and open a temporary file. 'suffix' -- The last part of the temporary file name, as for Python's 'mktemp' function. The file is open for reading and writing. The caller is responsible for deleting the file when finished with it. returns -- A pair '(file_name, file_descriptor)' for the temporary file.""" file_name = tempfile.mktemp(suffix) try: # Attempt to open the file. fd = os.open(file_name, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0600) except: exc_info = sys.exc_info() raise QMException, \ qm.error("temp file error", file_name=file_name, exc_class=str(exc_info[0]), exc_arg=str(exc_info[1])) return (file_name, fd) def open_temporary_file(mode = "w+b", suffix = ""): """Create and open a temporary file. 'mode' -- The mode argument to pass to 'fopen'. 'suffix' -- The last part of the temporary file name, as for Python's 'mktemp' function. Like 'open_temporary_file_fd', except that the second element of the return value is a file object.""" # This function can just use NamedTemporaryFile when QMTest requires # Python 2.3. file_name, fd = open_temporary_file_fd(suffix) return (file_name, os.fdopen(fd, mode)) def close_file_on_exec(fd): """Prevent 'fd' from being inherited across 'exec'. 'fd' -- A file descriptor, or object providing a 'fileno()' method. This function has no effect on Windows.""" if sys.platform != "win32": flags = fcntl.fcntl(fd, fcntl.F_GETFD) try: flags |= fcntl.FD_CLOEXEC except AttributeError: # The Python 2.2 RPM shipped with Red Hat Linux 7.3 does # not define FD_CLOEXEC. Fortunately, FD_CLOEXEC is 1 on # every UNIX system. flags |= 1 fcntl.fcntl(fd, fcntl.F_SETFD, flags) def copy(object): """Make a best-effort attempt to copy 'object'. returns -- A copy of 'object', if feasible, or otherwise 'object'.""" if type(object) is types.ListType: # Copy lists. return object[:] elif type(object) is types.DictionaryType: # Copy dictionaries. return object.copy() elif type(object) is types.InstanceType: # For objects, look for a method named 'copy'. If there is one, # call it. Otherwise, just return the object. copy_function = getattr(object, "copy", None) if callable(copy_function): return object.copy() else: return object else: # Give up. return object def wrap_lines(text, columns=72, break_delimiter="\\", indent=""): """Wrap lines in 'text' to 'columns' columns. 'text' -- The text to wrap. 'columns' -- The maximum number of columns of text. 'break_delimiter' -- Text to place at the end of each broken line (may be an empty string). 'indent' -- Text to place at the start of each line. The length of 'indent' does not count towards 'columns'. returns -- The wrapped text.""" # Break into lines. lines = string.split(text, "\n") # The length into which to break lines, leaving room for the # delimiter. new_length = columns - len(break_delimiter) # Loop over lines. for index in range(0, len(lines)): line = lines[index] # Too long? if len(line) > columns: # Yes. How many times will we have to break it? breaks = len(line) / new_length new_line = "" # Construct the new line, disassembling the old as we go. while breaks > 0: new_line = new_line \ + line[:new_length] \ + break_delimiter \ + "\n" + indent line = line[new_length:] breaks = breaks - 1 new_line = new_line + line # Replace the old line with the new. lines[index] = new_line # Indent each line. lines = map(lambda l, i=indent: i + l, lines) # Rejoin lines. return string.join(lines, "\n") def format_time(time_secs, local_time_zone=1): """Generate a text format representing a date and time. The output is in the format "YYYY-MM-DD HH:MM ZZZ". 'time_secs' -- The number of seconds since the start of the UNIX epoch, UTC. 'local_time_zone' -- If true, format the time in the local time zone. Otherwise, format it as UTC.""" # Convert the time in seconds to a Python time 9-tuple. if local_time_zone: time_tuple = time.localtime(time_secs) time_zone = time.tzname[time_tuple[8]] else: time_tuple = time.gmtime(time_secs) time_zone = "UTC" # Unpack the tuple. year, month, day, hour, minute, second, weekday, julian_day, \ dst_flag = time_tuple # Generate the format. return "%(year)4d-%(month)02d-%(day)02d " \ "%(hour)02d:%(minute)02d %(time_zone)s" % locals() def format_time_iso(time_secs=None): """Generate a ISO8601-compliant formatted date and time. The output is in the format "YYYY-MM-DDThh:mm:ss+TZ", where TZ is a timezone specifier. We always normalize to UTC (and hence always use the special timezone specifier "Z"), to get proper sorting behaviour. 'time_secs' -- The time to be formatted, as returned by e.g. 'time.time()'. If 'None' (the default), uses the current time. returns -- The formatted time as a string.""" if time_secs is None: time_secs = time.time() return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(time_secs)) def parse_time_iso(time_string): """Parse a ISO8601-compliant formatted date and time. See also 'format_time_iso'. 'time_string' -- The string to be parsed, as returned by e.g. 'format_time_iso'. returns -- The time as a float, like that returned by 'time.time'.""" return time.mktime(time.strptime(time_string, "%Y-%m-%dT%H:%M:%SZ")) def make_unique_tag(): """Return a unique tag string.""" global _unique_tag tag = "%d_%d" % (_unique_tag, os.getpid()) _unique_tag = _unique_tag + 1 return tag def split_argument_list(command): """Split a command into an argument list. 'command' -- A string containing a shell or similar command. returns -- An argument list obtained by splitting the command.""" # Strip leading and trailing whitespace. command = string.strip(command) # Split the command into argument list elements at spaces. argument_list = re.split(" +", command) return argument_list def parse_boolean(value): """Parse a boolean string. 'value' -- A string. returns -- True if 'value' is a true string, false if 'value' is a false string. raises -- 'ValueError' if 'value' is neither a true string, nor a false string.""" value = value.lower() if value in ("1", "true", "yes", "on"): return 1 elif value in ("0", "false", "no", "off"): return 0 else: raise ValueError, value def parse_string_list(value): """Parse a string list. 'value' -- A string. returns -- A list of strings. raises -- 'ValueError' if 'value' contains unbalanced quotes.""" # If the string doesn't contain quotes, simply split it. if "'" not in value and '"' not in value: return value.split() # Else split it manually at non-quoted whitespace only. breaks = [] esc = False quoted_1 = False # in '' quotes quoted_2 = False # in "" quotes value.strip() # Find all non-quoted space. for i, c in enumerate(value): if c == '\\': esc = not esc continue elif c == "'": if not esc and not quoted_2: quoted_1 = not quoted_1 elif c == '"': if not esc and not quoted_1: quoted_2 = not quoted_2 elif c in [' ', '\t']: # This is a breakpoint if it is neither quoted nor escaped. if not (quoted_1 or quoted_2 or esc): breaks.append(i) esc = False # Make sure quotes are matched. if quoted_1 or quoted_2 or esc: raise ValueError, value string_list = [] start = 0 for end in breaks: string_list.append(value[start:end]) start = end string_list.append(value[start:]) return [s.strip() for s in string_list if s not in [' ', '\t']] # No 'time.strptime' on non-UNIX systems, so use this instead. This # version is more forgiving, anyway, and uses our standardized timestamp # format. def parse_time(time_string, default_local_time_zone=1): """Parse a date and/or time string. 'time_string' -- A string representing a date and time in the format returned by 'format_time'. This function makes a best-effort attempt to parse incomplete strings as well. 'default_local_time_zone' -- If the time zone is not specified in 'time_string' and this parameter is true, assume the time is in the local time zone. If this parameter is false, assume the time is UTC. returns -- An integer number of seconds since the start of the UNIX epoch, UTC. Only UTC and the current local time zone may be specified explicitly in 'time_string'.""" # Sanitize. time_string = string.strip(time_string) time_string = re.sub(" +", " ", time_string) time_string = re.sub("/", "-", time_string) # On Windows, "UTC" is spelled "GMT Standard Time". Change that # to "UTC" so that we can process it with the same code we use # for UNIX. time_string = re.sub("GMT Standard Time", "UTC", time_string) # Break it apart. components = string.split(time_string, " ") # Do we have a time zone at the end? if components[-1] == "UTC": # It's explicitly UTC. utc = 1 dst = 0 components.pop() elif components[-1] == time.tzname[0]: # It's explicitly our local non-DST time zone. utc = 0 dst = 0 components.pop() elif time.daylight and components[-1] == time.tzname[1]: # It's explicitly our local DST time zone. utc = 0 dst = 1 components.pop() else: # No explicit time zone. Use the specified default. if default_local_time_zone: utc = 0 dst = -1 else: utc = 1 dst = 0 # Start with the current time, in the appropriate format. if utc: time_tuple = time.gmtime(time.time()) else: time_tuple = time.localtime(time.time()) # Unpack the date tuple. year, month, day = time_tuple[:3] # Assume midnight. hour = 0 minute = 0 # Look at each part of the date/time. for component in components: if string.count(component, "-") == 2: # Looks like a date. year, month, day = map(int, string.split(component, "-")) elif string.count(component, ":") in [1, 2]: # Looks like a time. hour, minute = map(int, string.split(component, ":")[:2]) else: # Don't understand it. raise ValueError # Construct a Python time tuple. time_tuple = (year, month, day, hour, minute, 0, 0, 0, dst) # Convert it to seconds. if utc: return int(timegm(time_tuple)) else: return int(time.mktime(time_tuple)) def parse_assignment(assignment): """Parse an 'assignment' of the form 'name=value'. 'aassignment' -- A string. The string should have the form 'name=value'. returns -- A pair '(name, value)'.""" # Parse the assignment. try: (name, value) = string.split(assignment, "=", 1) return (name, value) except: raise QMException, \ qm.error("invalid keyword assignment", argument=assignment) def read_assignments(file): """Read assignments from a 'file'. 'file' -- A file object containing the context. When the file is read, leading and trailing whitespace is discarded from each line in the file. Then, lines that begin with a '#' and lines that contain no characters are discarded. All other lines must be of the form 'NAME=VALUE' and indicate an assignment to the context variable 'NAME' of the indicated 'VALUE'. returns -- A dictionary mapping each of the indicated 'NAME's to its corresponding 'VALUE'. If multiple assignments to the same 'NAME' are present, only the 'VALUE' from the last assignment is stored.""" # Create an empty dictionary. assignments = {} # Read all the lines in the file. lines = file.readlines() # Strip out leading and trailing whitespace. lines = map(string.strip, lines) # Drop any lines that are completely blank or lines that are # comments. lines = filter(lambda x: x != "" and not x.startswith("#"), lines) # Go through each of the lines to process the context assignment. for line in lines: # Parse the assignment. (name, value) = parse_assignment(line) # Add it to the context. assignments[name] = value return assignments def get_username(): """Returns the current username as a string. This is our best guess as to the username of the user who is actually logged in, as opposed to the effective user id used for running tests. If the username cannot be found, raises a 'QMException'.""" # First try using the 'getpass' module. try: return getpass.getuser() except: pass # 'getpass' doesn't necessarily work on Windows, so if that fails, # try the win32 function. try: import win32api except ImportError: pass else: try: return win32api.GetUserName() except: raise PythonException("Error accessing win32 user database", *sys.exc_info()[:2]) # And if none of that worked, give up. raise QMException, "Cannot determine user name." def get_userid(): """Returns the current user id as an integer. This is the real user id, not the effective user id, to better track who is actually running the tests. If the user id cannot be found or is not defined, raises a 'QMException'.""" try: uid = os.getuid() except AttributeError: raise QMException, "User ids not supported on this system." return uid def html_to_text(html, width=72): """Renders HTML to text in a simple way. 'html' -- A string containing the HTML code to be rendered. 'width' -- Column at which to word-wrap. Default 72. returns -- A string containing a plain text rendering of the HTML.""" s = StringIO.StringIO() w = formatter.DumbWriter(s, width) f = formatter.AbstractFormatter(w) p = htmllib.HTMLParser(f) p.feed(html) p.close() return s.getvalue() ######################################################################## # variables ######################################################################## rc = RcConfiguration() """The configuration stored in system and user rc files.""" # The next number to be used when handing out unqiue tag strings. _unique_tag = 0 ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/platform.py0000664000076400007640000000550011107032237015176 0ustar stefanstefan######################################################################## # # File: platform.py # Author: Alex Samuel # Date: 2001-04-30 # # Contents: # Platform-specific code. # # Copyright (c) 2001, 2002 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import common import os import qm import string import sys ######################################################################## # classes ######################################################################## class MailError(common.QMException): pass ######################################################################## # initialization ######################################################################## if sys.platform == "win32": from platform_win32 import * else: from platform_unix import * ######################################################################## # functions ######################################################################## def get_shell_for_command(): """Return the command shell to use when running a single shell command. returns -- A sequence of argument list entries to use when invoking the shell. The first element of the list is the shell executable path. The command should be appended to the argument list.""" shell = common.rc.Get("command_shell", None, "common") if shell is not None: # Split the configuration value into an argument list. return common.split_argument_list(shell) else: if sys.platform == "win32": shell = default_shell + ["/c"] else: shell = default_shell + ["-c"] return shell def get_shell_for_script(): """Return the command shell to use when running a shell script. returns -- A sequence of argument list entries to use when running a shell script. The first element of the list is the shell executable. The name of the script should be appended to the argument list.""" shell = common.rc.Get("script_shell", None, "common") if shell is not None: # Split the configuration value into an argument list. return common.split_argument_list(shell) else: # On Windows, add the "/c" switch; that is needed even when # invoking a script. if sys.platform == "win32": shell = default_shell + ["/c"] else: # Use the default, but copy it so the caller can change it. shell = default_shell[:] return shell ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/setup.py0000664000076400007640000000403711107032237014516 0ustar stefanstefan######################################################################## # # File: setup.py # Author: Mark Mitchell # Date: 01/02/2002 # # Contents: # QM Distutils setup script. # # Copyright (c) 2002 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## from distutils.core import setup import os import os.path import string ######################################################################## # Functions ######################################################################## def find_packages_r(packages, dirname, names): """If 'dirname' is a QM package, add it to 'packages'. 'packages' -- A mutable sequence of package names. 'dirname' -- The (relative) path from the base of the QM package to the directory. 'names' -- A mutable sequence of file names indicating files (and directories) contained in the directory given by 'dirname'.""" # If the directory contains a file called __init__.py, it is a # package. Directories named "classes" contain extension classes. if "__init__.py" in names or os.path.basename(dirname) == "classes": # Replace a leading "." with "qm". d = "qm" + dirname[1:] # Replace path separators with periods. d = string.replace(d, os.sep, ".") if os.altsep: d = string.replace(d, os.altsep, ".") packages.append(d) # Exclude directories named "build"; they are created by Distutils. if "build" in names: names.remove("build") ######################################################################## # Main Program ######################################################################## # Find all of the packages that make up QM. packages = [] os.path.walk(".", find_packages_r, packages) setup(name="qm", version="1.1", packages=packages, package_dir={ 'qm' : '.' }) qmtest-2.4.1/qm/temporary_directory.py0000664000076400007640000000516211107032237017464 0ustar stefanstefan######################################################################## # # File: temporary_directory.py # Author: Mark Mitchell # Date: 05/07/2003 # # Contents: # TemporaryDirectory # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## import dircache import os import qm import sys import tempfile ######################################################################## # Classes ######################################################################## class TemporaryDirectory: """A 'TemporaryDirectory' is a directory for temporary files. Creating a new 'TemporaryDirectory results in the creation of a new directory in the file system. The directory is automatically removed from the file system when the 'TemporaryDirectory' is destroyed.""" def __init__(self): """Construct a new 'TemporaryDirectory.""" self.__directory = None dir_path = tempfile.mktemp() try: os.mkdir(dir_path, 0700) except: exc_info = sys.exc_info() raise qm.common.QMException, \ qm.error("temp dir error", dir_path=dir_path, exc_class=str(exc_info[0]), exc_arg=str(exc_info[1])) self.__directory = dir_path def GetPath(self): """Returns the path to the temporary directory. returns -- The path to the temporary directory.""" return self.__directory def __del__(self): self.Remove() def Remove(self): """Remove the temporary directory. Removes the temporary directory, and all files and directories contained within it, from the file system.""" if self.__directory is not None: self.__RemoveDirectory(self.__directory) self.__directory = None def __RemoveDirectory(self, path): """Remove the directory 'path'. Removes 'path', after first removing all of its contents.""" # Remove everything in the directory. for entry in dircache.listdir(path): entry_path = os.path.join(path, entry) if os.path.isdir(entry_path): self.__RemoveDirectory(entry_path) else: os.unlink(entry_path) # Remove the directory itself. os.rmdir(path) qmtest-2.4.1/qm/user.py0000664000076400007640000004545311107032237014343 0ustar stefanstefan######################################################################## # # File: user.py # Author: Alex Samuel # Date: 2001-03-23 # # Contents: # User management facilities. # # Copyright (c) 2001, 2002 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## """User management facilities. Access to this module is primarily through two global variables. 'database' -- The user database. The database contains objects representing users, accessed via a *user ID*. The user ID is a label uniquely identifying the user in the system. The user database also provides a notion of user groups. Each group is identified by a group ID, and contains zero or more user IDs. A user may belong to more than one group. A group may not contain other groups. 'authenticator' -- The authenticator object by which the application authenticates users who attempt to access it via various channels. Access the database object via this interface: * Use the database object as a Python map from user IDs to 'User' objects. The 'keys' method returns a sequence of user IDs in the database. * Call 'GetGroupIds' to return a sequence of group IDs. Use the 'GetGroup' method to retrieve a 'Group' object for a given group ID. """ ######################################################################## # imports ######################################################################## import qm import label import xmlutil ######################################################################## # constants ######################################################################## xml_user_database_dtd = "-//Software Carpentry//User Database V0.1//EN" ######################################################################## # classes ######################################################################## class AuthenticationError(Exception): pass class XmlDatabaseError(Exception): pass class AccountDisabledError(AuthenticationError): pass class User: """A user account record. User accounts contain three sets of properties. Each property is a name-value pair. The three sets of properties are: informational properties -- General information about the user. This may include the user's real name, contact information, etc. These properties are generally user-visible, and should be modified only at the user's request. configuration properties -- Program-specific per-user configuration. This includes user's preferences, such as preferred layout and output options. These properties are typically hidden as implementation details, and are often changed implicitly as part of other operations. authentication properties -- Information used to authenticate the user. This may include such things as passwords, PGP keys, and digital certificates. There are no accessors for these properties; they should be used by authenticators only. """ def __init__(self, user_id, role="user", enabled=1, information_properties={}, configuration_properties={}, authentication_properties={}): """Create a new user account. 'user_id' -- The ID for the user. 'role' -- If "default", this is the default user account (there should be only one). The default account, if provided, is used for otherwise unauthenticated operations. If "admin", this is an administrator account. If "user", this is an ordinary user account. 'enabled' -- If true, this account is enabled; otherwise, disabled. 'information_properties' -- A map contianing information properties. 'configuration_properties' -- A map containing configuration properties. 'authentication_properties' -- A map containing authentication properties.""" self.__id = user_id self.__role = role self.__is_enabled = enabled # Initialize properties. self.__authentication = authentication_properties.copy() self.__configuration = configuration_properties.copy() self.__info = information_properties.copy() def GetId(self): """Return the user ID of this user.""" return self.__id def GetRole(self): """Return the role of this user.""" return self.__role def IsEnabled(self): """Return true if this account is enabled.""" return self.__is_enabled def GetConfigurationProperty(self, name, default=None): """Return a configuration property. 'name' -- The name of the property. 'default' -- The value to return if this property is not specified for the user account.""" return self.__configuration.get(name, default) def SetConfigurationProperty(self, name, value): """Set the configuration property 'name' to 'value'.""" self.__configuration[name] = value def GetInfoProperty(self, name, default=None): """Return an informational property. 'name' -- The name of the property. 'default' -- The value to return if this property is not specified for the user account.""" return self.__info.get(name, default) def SetInfoProperty(self, name, value): """Set the informational property 'name' to 'value'.""" self.__info[name] = value class Group: """A group of users. A 'Group' object is treated as an ordinary list of user IDs (except that a user ID may not appear more than once in the list).""" def __init__(self, group_id, user_ids=[]): """Create a new group. 'group_id' -- The ID of this group. 'user_ids' -- IDs of users initially in the group.""" self.__id = group_id self.__user_ids = list(user_ids) def GetId(self): """Return the group_id of this group.""" return self.__id def __len__(self): return len(self.__user_ids) def __getitem__(self, index): return self.__user_ids[index] def __setitem__(self, index, user_id): self.__user_ids[index] = user_id # Make sure 'user_id' appears only once. while self.__user_ids.count(user_id) > 1: self.__user_ids.remove(user_id) def __delitem__(self, index): del self.__user_ids[index] def append(self, user_id): # Don't add a given user more than once. if user_id not in self.__user_ids: self.__user_ids.append(user_id) def remove(self, user_id): self.__user_ids.remove(user_id) class Authenticator: """Base class for authentication classes. An 'Authenticator' object is responsible for determining the authenticity of a user. The inputs to an authentication action depend on the mechanism with which the user communicates with the program -- for instance, a web request, command invocation, or email message.""" def AuthenticateDefaultUser(self): """Authenticate for the default user, if one is provided. returns -- The user ID of the default user.""" raise NotImplementedError def AuthenticateWebRequest(self, request): """Authenticate a login web request. 'request' -- A web request containing the user's login information. returns -- The user ID of the authenticated user.""" raise NotImplementedError class DefaultDatabase: default_user = User("default_user", "default") def GetDefaultUserId(self): return self.default_user.GetId() def keys(self): return [self.GetDefaultUserId()] def __getitem__(self, user_id): default_user_id = self.default_user.GetId() if user_id == default_user_id: return self.default_user else: raise KeyError, user_id def get(self, user_id, default=None): default_user_id = self.default_user.GetId() if user_id == default_user_id: return self.default_user else: return None def GetGroupIds(self): return [] def GetGroup(self, group_id): raise KeyError, "no such group" class DefaultAuthenticator(Authenticator): """Authenticator for only a single user, "default_user".""" def AuthenticateDefaultUser(self): return DefaultDatabase.default_user.GetId() def AuthenticateWebRequest(self, request): raise AuthenticationError class XmlDatabase: """An XML user database. An object of this class behaves as a read-only map from user IDs to 'User' objects.""" def __init__(self, database_path): """Read in the XML user database.""" document = xmlutil.load_xml_file(database_path) self.__path = database_path node = document.documentElement assert node.tagName == "users" self.__users = {} self.__groups = {} self.__default_user_id = None # Load users. for user_node in node.getElementsByTagName("user"): user = get_user_from_dom(user_node) # Store the account. self.__users[user.GetId()] = user # Make note if this is the default user. if user.GetRole() == "default": if self.__default_user_id is not None: # More than one default user was specified. raise XmlDatabaseError, "multiple default users" self.__default_user_id = user.GetId() # Load groups. for group_node in node.getElementsByTagName("group"): group = get_group_from_dom(group_node) # Make sure all the user IDs listed for this group are IDs # we know. for user_id in group: if not self.__users.has_key(user_id): raise XmlDatabaseError, \ 'user "%s" in group "%s" is unknown' \ % (user_id, group.GetId()) # Store the group. self.__groups[group.GetId()] = group def GetDefaultUserId(self): """Return the ID of the default user, or 'None'.""" return self.__default_user_id def GetGroupIds(self): """Return the IDs of user groups.""" return self.__groups.keys() def GetGroup(self, group_id): """Return the group with ID 'group_id'.""" return self.__groups[group_id] def Write(self): """Write out the user database.""" # Create a DOM document for the database. document = xmlutil.create_dom_document( public_id = "User", document_element_tag="users" ) document_element = document.documentElement # Create elements for users in the database. for user in self.__users.values(): user_element = create_dom_for_user(document, user) document_element.appendChild(user_element) # Create elements for user groups. for group in self.__groups.values(): group_element = create_dom_for_group(document, group) document_element.appendChild(group_element) # Write out the database. document.writexml(open(self.__path, "w")) # Methods for emulating a map object. def __getitem__(self, user_id): return self.__users[user_id] def get(self, user_id, default=None): return self.__get(user_id, default) def keys(self): return self.__users.keys() class XmlDatabaseAuthenticator(Authenticator): """An authenticator based on contents of the XML user database.""" def __init__(self, database): """Create a new authenticator. Authentication is performed based on information stored in 'XmlDatabase' instance 'database'.""" assert isinstance(database, XmlDatabase) self.__database = database def AuthenticateDefaultUser(self): # Try to perform a password authentication for the default user # with an empty password. default_user_id = self.__database.GetDefaultUserId() return self.AuthenticatePassword(default_user_id, "") def AuthenticateWebRequest(self, request): # Extract the user name and password from the web request. user_name = request["_login_user_name"] password = request["_login_password"] return self.AuthenticatePassword(user_name, password) def AuthenticatePassword(self, user_name, password): try: # Look up the user ID. user = database[user_name] expected_password = user._User__authentication.get("password", None) except KeyError: # No user was found with this user ID. expected_password = None if expected_password is None \ or expected_password != password: # No password specified for this user, or the provided # password doesn't match. raise AuthenticationError, "invalid user name/password" # Is the account enabled? if not user.IsEnabled(): # No. Prevent authentication. raise AccountDisabledError, user_name return user_name ######################################################################## # functions ######################################################################## def load_xml_database(path): """Load users from XML database at 'path' and set up authenticator.""" global database global authenticator # Use a finally block to make sure either both are set, or neither. try: xml_database = XmlDatabase(path) xml_authenticator = XmlDatabaseAuthenticator(xml_database) except: raise else: database = xml_database authenticator = xml_authenticator def get_user_from_dom(user_node): """Construct a 'User' object from a user DOM element. 'user_node' -- A "user" DOM element. returns -- A 'User' object.""" assert user_node.tagName == "user" # The user ID is stored in the ID attribute of the user element. user_id = user_node.getAttribute("id") # Also the role. role = user_node.getAttribute("role") # Determine whether the account is disabled. enabled = user_node.getAttribute("disabled") == "no" # Read properties. info_properties = _get_dom_properties(user_node, "info") auth_properties = _get_dom_properties(user_node, "authentication") conf_properties = _get_dom_properties(user_node, "configuration") # Create the user object. return User(user_id, role, enabled, info_properties, conf_properties, auth_properties) def _get_dom_properties(node, tag): """Return a dictionary of properties from a user DOM element node. 'node' -- A "user" DOM element. 'tag' -- The tag of the child element in which to look for properties. returns -- A map from property names to values.""" # Find all child elements of 'node' with 'tag'. elements = node.getElementsByTagName(tag) if len(elements) == 0: # The child may be omitted; that's OK. return {} # There element, if provided, should be unique. assert len(elements) == 1 element = elements[0] # Start a map of properties. properties = {} # Loop over property sub-elements. for property_node in element.getElementsByTagName("property"): # The property name is stored in the name attribute. name = property_node.getAttribute("name") # The property value is stored as a child text node. value = xmlutil.get_dom_text(property_node) properties[name] = value return properties def create_dom_for_user(document, user): """Create a DOM element node for 'user'. 'document' -- The DOM document object in which to create the element. 'user' -- A 'User' instance. returns -- A DOM element node.""" # Create the user element. element = document.createElement("user") element.setAttribute("id", user.GetId()) element.setAttribute("role", user.GetRole()) if user.IsEnabled(): disabled_attribute = "no" else: disabled_attribute = "yes" element.setAttribute("disabled", disabled_attribute) # Add informational properties. info_properties_element = document.createElement("info") _create_dom_properties(info_properties_element, user._User__info) element.appendChild(info_properties_element) # Add authentication properties. auth_properties_element = document.createElement("authentication") _create_dom_properties(auth_properties_element, user._User__authentication) element.appendChild(auth_properties_element) # Add configuration properties. conf_properties_element = document.createElement("configuration") _create_dom_properties(conf_properties_element, user._User__configuration) element.appendChild(conf_properties_element) # All done. return element def _create_dom_properties(element, properties): """Add user properties to a DOM element. 'element' -- A DOM element node to which properties are to be added as children. 'properties' -- A map from property names to values.""" document = element.ownerDocument for name, value in properties.items(): prop_element = xmlutil.create_dom_text_element( document, "property", str(value)) prop_element.setAttribute("name", name) element.appendChild(prop_element) def get_group_from_dom(group_node): """Construct a 'Group' object from a DOM element. 'group_node' -- A DOM "group" element node. returns -- A 'Group' object.""" assert group_node.tagName == "group" group_id = group_node.getAttribute("id") user_ids = xmlutil.get_child_texts(group_node, "user-id") # Make the group. return Group(group_id, user_ids) def create_dom_for_group(document, group): """Create a DOM element node for 'group'. 'document' -- The DOM document object in which to create the element. 'group' -- A 'Group' instance. returns -- A DOM element node.""" element = document.createElement("group") element.setAttribute("id", group.GetId()) for user_id in group: user_id_element = xmlutil.create_dom_text_element( document, "user-id", user_id) element.appendChild(user_id_element) return element ######################################################################## # variables ######################################################################## database = DefaultDatabase() authenticator = DefaultAuthenticator() ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/dist/0000775000076400007640000000000011122067201013737 5ustar stefanstefanqmtest-2.4.1/qm/dist/__init__.py0000775000076400007640000000000011107032235016043 0ustar stefanstefanqmtest-2.4.1/qm/dist/command/0000775000076400007640000000000011122067201015355 5ustar stefanstefanqmtest-2.4.1/qm/dist/command/__init__.py0000775000076400007640000000000011107032235017461 0ustar stefanstefanqmtest-2.4.1/qm/dist/command/build_extensions.py0000664000076400007640000000365311107032235021316 0ustar stefanstefan######################################################################## # # File: build_extensions.py # Author: Stefan Seefeld # Date: 2005-11-16 # # Contents: # Command to build qmtest extensions. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm.xmlutil from distutils.command.build_py import build_py from distutils.util import get_platform import os, sys, dircache ######################################################################## # Classes ######################################################################## class build_extensions(build_py): """build extension files.""" description = "build qmtest extension classes." def finalize_options(self): b = self.distribution.get_command_obj('build') b.ensure_finalized() base = b.build_base build_py.finalize_options(self) self.build_dir = os.path.join(base, 'ext') if self.distribution.ext_modules: plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3]) self.build_dir += plat_specifier self.extensions = self.distribution.qmtest_extensions def get_input(self): """Return all files containing extension classes.""" files = [os.path.join(self.extensions, f) for f in dircache.listdir(self.extensions) if f.endswith('.py') or f == 'classes.qmc'] return files def run(self): self.mkpath(self.build_dir) for f in self.get_input(): basename = os.path.basename(f) self.copy_file(f, os.path.join(self.build_dir, basename), preserve_mode=0) qmtest-2.4.1/qm/dist/command/install_extensions.py0000664000076400007640000001141011107032235021653 0ustar stefanstefan######################################################################## # # File: install_extensions.py # Author: Stefan Seefeld # Date: 2005-11-16 # # Contents: # Command to install qmtest extensions. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm.xmlutil from distutils.command.install_lib import install_lib import os, dircache, xml ######################################################################## # Classes ######################################################################## def _compare_files(a, b): """Compare the content of two files. 'a' -- Filename of first file to be compared. 'b' -- Filename of second file to be compared. returns -- True if both files have the same content, False otherwise.""" file_a, file_b = open(a, 'r'), open(b, 'r') for line in file_a: if line != file_b.readline(): return False if file_b.readline(): return False return True class install_extensions(install_lib): """Install extension files.""" description = "install qmtest extension classes." def finalize_options(self): if not self.install_dir: i = self.distribution.get_command_obj('install') i.ensure_finalized() prefix = i.root or i.prefix self.install_dir = os.path.join(prefix, qm.extension_path) install_lib.finalize_options(self) b = self.distribution.get_command_obj('build_extensions') b.ensure_finalized() self.build_dir = b.build_dir def run(self): # Make sure we have built everything we need first self.run_command('build_extensions') if not os.path.isdir(self.install_dir): self.mkpath(self.install_dir) if not os.path.exists(os.path.join(self.install_dir, 'classes.qmc')): # This is the first time extensions are installed there. self.copy_tree(self.build_dir, self.install_dir) else: # Test that to-be-copied modules don't overwrite existing ones: old_files = [f for f in dircache.listdir(self.install_dir) if f.endswith('.py')] new_files = [f for f in dircache.listdir(self.build_dir) if f.endswith('.py') and f != '__init__.py'] overlap = [] for f in new_files: if f in old_files: # Don't complain if both files are identical. if not _compare_files(os.path.join(self.build_dir, f), os.path.join(self.install_dir, f)): overlap.append(f) if overlap: print "Error: The following extension files already exist:" for o in overlap: print " %s"%o return # Copy all modules to the install directory. for f in new_files: self.copy_file(os.path.join(self.build_dir, f), os.path.join(self.install_dir, f), preserve_mode=0) # Carefully merge the new extensions into an existing repository. old_qmc = qm.xmlutil.load_xml_file(os.path.join(self.install_dir, 'classes.qmc')) old_root = old_qmc.documentElement new_qmc = qm.xmlutil.load_xml_file(os.path.join(self.build_dir, 'classes.qmc')) new_root = new_qmc.documentElement for ext in new_root.getElementsByTagName("class"): # If this entry already exists in the repository, skip it. name = ext.getAttribute("name") entries = [c for c in old_root.childNodes if c.nodeType == xml.dom.Node.ELEMENT_NODE and c.tagName == "class" and c.getAttribute("name") == name] if not entries: old_root.appendChild(ext) old_root.appendChild(old_qmc.createTextNode('\n')) # Write new repository file. old_qmc.writexml(open(os.path.join(self.install_dir, 'tmp-classes.qmc'), 'w')) # If that worked, update the original one. os.rename(os.path.join(self.install_dir, 'tmp-classes.qmc'), os.path.join(self.install_dir, 'classes.qmc')) qmtest-2.4.1/qm/dist/distribution.py0000664000076400007640000000312311107032235017031 0ustar stefanstefan######################################################################## # # File: setup.py # Author: Stefan Seefeld # Date: 2005-11-16 # # Contents: # Distribution class adding 'install_extensions' command. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from distutils import dist from qm.dist.command.build_extensions import build_extensions from qm.dist.command.install_extensions import install_extensions class Distribution(dist.Distribution): def __init__(self, attrs=None): # Set up the Distribution class to make it aware of the additional # commands. First we need to add an attribute so setup() can pass # a 'qmtest_extensions' parameter. self.qmtest_extensions = None dist.Distribution.__init__(self, attrs) # Now add our own commands to the list. self.cmdclass['build_extensions'] = build_extensions self.cmdclass['install_extensions'] = install_extensions # Register the command as a sub-command of 'install' def has_extensions(cmd): return self.qmtest_extensions build = self.get_command_class('build') build.sub_commands.append(('build_extensions', has_extensions)) install = self.get_command_class('install') install.sub_commands.append(('install_extensions', has_extensions)) qmtest-2.4.1/qm/xmlutil.py0000664000076400007640000001501011107032237015045 0ustar stefanstefan######################################################################## # # File: xmlutil.py # Author: Alex Samuel # Date: 2001-03-18 # # Contents: # Miscellaneous XML-related functions. # # Copyright (c) 2001, 2002 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import os import qm import re import xml.dom import xml.dom.minidom ######################################################################## # functions ######################################################################## def make_public_id(name): """Return a public ID for the DTD with the given 'name'. 'name' -- The name of the DTD. returns -- A public ID for the DTD.""" return "-//QM/%s/%s//EN" % (qm.version, name) def make_system_id(name): """Return a system ID for the DTD with the given 'name'. 'name' -- The name of the DTD, as a relative UNIX path. returns -- A URL for the DTD.""" return "http://www.codesourcery.com/qm/dtds/%s/%s" % (qm.version, name) def load_xml_file(path): """Return a DOM document loaded from the XML file 'path'.""" # Open the file. file = open(path, "r") return load_xml(file) def load_xml(file): """Return a DOM document loaded from the XML file object 'file'. 'file' -- A file object, opened for reading. returns -- The DOM document contained in 'file'. This function closes 'file', whether or not reading the document was successful.""" try: document = xml.dom.minidom.parse(file) finally: file.close() return document def get_dom_text(node): """Return the text contained in DOM 'node'. 'node' -- A DOM element node. prerequisites -- 'node' is an element node with exactly one child, which is a text node.""" assert node.nodeType == xml.dom.Node.ELEMENT_NODE # Normalize the node so that multiple TEXT_NODEs are collapsed into # a single node. node.normalize() # If there are no children, the string is empty. if len(node.childNodes) == 0: return "" # If there is a child, there should be only one. if len(node.childNodes) != 1: raise QMException, "Invalid XML text node." child = node.childNodes[0] if child.nodeType != xml.dom.Node.TEXT_NODE: raise QMException, "Invalid XML text node." return child.data def child_tag_predicate(child_tag): """Return a predicate function for finding element nodes by tag. returns -- A predicate function that takes a node as its argument and returns true if the node is an element node whose tag is 'child_tag'.""" return lambda node, tag=child_tag: \ node.nodeType == xml.dom.Node.ELEMENT_NODE \ and node.tagName == tag def get_child(node, child_tag): """Return the child element node of 'node' whose tag is 'child_tag'. 'node' -- A DOM node. It must have exactly one element child with the tag 'child_tag'. 'child_tag' -- The desired element tag. returns -- A child DOM node of 'node'. raises -- 'KeyError' if 'node' has no element child with tag 'child_tag', or more than one.. """ matching_children = \ filter(child_tag_predicate(child_tag), node.childNodes) if len(matching_children) != 1: raise KeyError, child_tag return matching_children[0] def get_child_text(node, child_tag, default=None): """Return the text contained in a child of DOM 'node'. 'child_tag' -- The tag of the child node whose text is to be retrieved. 'default' -- If 'node' has no child element with tag 'child_tag', returns 'default', unless 'default' is 'None'. raises -- 'KeyError' if 'default' is 'None' and 'node' has no child element with tag 'child_tag'.""" try: return get_dom_text(get_child(node, child_tag)) except KeyError: if default is not None: return default else: raise def get_child_texts(node, child_tag): """Return a sequence of text contents of children. 'node' -- A DOM node. returns -- The list containing all child nodes of 'node' which have tag 'child_tag'. Each child must have exactly one child of its own, which must be a text node.""" return map(get_dom_text, node.getElementsByTagName(child_tag)) def create_dom_text_element(document, tag, text): """Return a DOM element containing a single text node. 'document' -- The containing DOM document. 'tag' -- The element tag. 'text' -- The text contents of the text node.""" element = document.createElement(tag) if text != "": text_node = document.createTextNode(text) element.appendChild(text_node) else: # Don't create a child node in this case. For some reason, it # gets written out with an extraneous newline, and therefore # when the text is read in, its no longer an empty string. pass return element __dom_implementation = xml.dom.minidom.getDOMImplementation() def create_dom_document(public_id, document_element_tag): """Create a DOM document. 'public_id' -- The (partial) public ID for the DTD. 'document_element_tag' -- The tag of the main document element. returns -- A DOM document node.""" public_id = make_public_id(public_id) system_id = make_system_id(public_id.lower() + ".dtd") # Create the document type for the XML document. document_type = __dom_implementation.createDocumentType( qualifiedName=document_element_tag, publicId=public_id, systemId=system_id ) # Create a new DOM document. document = __dom_implementation.\ createDocument(namespaceURI=None, qualifiedName=document_element_tag, doctype=document_type) return document __hyphen_regex = re.compile("(--+)") def __hyphen_replacement(match): return "-" + " -" * (len(match.group(0)) - 1) def sanitize_text_for_comment(text): """Return 'text' modified so that it is valid for an XML comment.""" # A comment cannot contain two or more hyphens in a row. text = __hyphen_regex.sub(__hyphen_replacement, text) return text ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/platform_unix.py0000664000076400007640000001052511120045476016250 0ustar stefanstefan######################################################################## # # File: platform_unix.py # Author: Alex Samuel # Date: 2001-05-13 # # Contents: # Platform-specific function for UNIX and UNIX-like systems. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import base64 import common import cPickle import cStringIO import os import posix import qm import quopri import select import signal import string import sys import traceback ######################################################################## # constants ######################################################################## if sys.platform[:5] == "linux": # GNU/Linux systems generally use 'bash' as the default shell. # Invoke it with options to inhibit parsing of user startup files. default_shell = ["/bin/bash", "-norc", "-noprofile"] else: # Other UNIX systems use the Bourne shell. default_shell = ["/bin/sh"] ######################################################################## # classes ######################################################################## class SignalException(common.QMException): """An exception raised in response to a signal.""" def __init__(self, signal_number): """Create a new signal exception. 'signal_number' -- The signal number.""" # Construct a text argument for the exception. message = "Signal %d" % signal_number # Include the signal name, if available. signal_name = get_signal_name(signal_number) if signal_name is not None: message = message + " (%s)" % signal_name # Initialize the base class. common.QMException.__init__(self, message) # Store the signal number. self.__signal_number = signal_number def GetSignalNumber(self): """Return the number of the signal that caused this exception.""" return self.__signal_number ######################################################################## # functions ######################################################################## def open_in_browser(url): """Open a browser window and point it at 'url'. The browser is run in a separate, independent process.""" # Escape single quotes in the URL. url = string.replace(url, "'", "%27") # Which browser to use? browser = common.rc.Get("browser", "mozilla", "common") # Invoke the browser. os.system("%s '%s' &" % (browser, url)) def get_signal_name(signal_number): """Return the name for signal 'signal_number'. returns -- The signal's name, or 'None'.""" # A hack: look for an attribute in the 'signal' module whose # name starts with "SIG" and whose value is the signal number. for attribute_name in dir(signal): if len(attribute_name) > 3 \ and attribute_name[:3] == "SIG" \ and getattr(signal, attribute_name) == signal_number: return attribute_name # No match. return None def install_signal_handler(signal_number): """Install a handler to translate a signal into an exception. The signal handler raises a 'SignalException' exception in response to a signal.""" signal.signal(signal_number, _signal_handler) def _signal_handler(signal_number, execution_frame): """Generic signal handler that raises an exception.""" raise SignalException(signal_number) def get_host_name(): """Return the name of this computer.""" return posix.uname()[1] ######################################################################## # initialization ######################################################################## def _initialize(): """Perform module initialization.""" # Install signal handlers for several common signals. for s in (signal.SIGALRM, signal.SIGHUP, signal.SIGTERM, signal.SIGUSR1, signal.SIGUSR2): install_signal_handler(s) _initialize() ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/lock.py0000664000076400007640000000175211107032237014307 0ustar stefanstefan######################################################################## # # File: lock.py # Author: Mark Mitchell # Date: 07/03/2002 # # Contents: # Lock # # Copyright (c) 2002 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Notes ######################################################################## # On systems that do not support threads, Threading.Lock() is # unavailable. This module provides a class with the same interface # that works on systems without threads. try: import thread from threading import Lock, RLock except: class Lock: def acquire(blocking = 1): # The lock can always be acquired. pass def release(): # There is nothing to do to release the lock. pass class RLock(Lock): pass qmtest-2.4.1/qm/executable.py0000664000076400007640000011357011107032237015502 0ustar stefanstefan######################################################################## # # File: executable.py # Author: Mark Mitchell # Date: 11/14/2002 # # Contents: # Executable, RedirectedExecutable # # Copyright (c) 2002, 2003 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ####################################################################### import os import qm.common import signal import string import sys import time # The classes in this module are implemented differently depending on # the operating system in use. if sys.platform == "win32": import msvcrt import pywintypes from threading import * import win32api import win32con import win32event import win32file import win32pipe import win32process else: import cPickle import fcntl import select import qm.sigmask ######################################################################## # Classes ####################################################################### class Executable(object): """An 'Executable' is a program that the operating system can run. 'Exectuable' (and classes derived from it) create child processes. The 'Spawn' function creates child processes that execute asynchronously. The 'Run' function creates child processes that execute synchrounously, i.e,. the 'Run' function does not return until the child process has completed its execution. It is safe to reuse a particular 'Executable' instance (by calling 'Spawn' or 'Run' more than once), so long as the uses are not interleaved.""" def Spawn(self, arguments=[], environment = None, dir = None, path = None, exception_pipe = None): """Spawn the program. 'arguments' -- The sequence of arguments that should be passed to the executable. The first argument provided in this sequence will be 'argv[0]'; that is also the value used for the path to the executable. 'environment' -- If not 'None', a dictionary giving the environment that should be provided to the child. 'dir' -- If not 'None', the directory in which the child should begin execution. If 'None', the child will execute in the same directory as the parent. 'path' -- If not 'None', the path to the program to run. If 'None', 'arguments[0]' is used. 'exception_pipe' -- If not 'None', a pipe that the child can use to communicate an exception to the parent. This pipe is only used on UNIX systems. The write end of the pipe will be closed by this function. returns -- The PID of the child. Before creating the child, the parent will call 'self._InitializeParent'. On UNIX systems, the child will call 'self._InitializeChild' after 'fork', but before 'exec'. On non-UNIX systems, 'self._InitializeChild' will never be called. After creating the child, 'self._HandleChild' is called in the parent. This hook should be used to handle tasks that must be performed after the child is running. If the path to the program is absolute, or contains no separator characters, it is not modified. Otherwise the path to the program is relative, it is transformed into an absolute path using 'dir' as the base, or the current directory if 'dir' is not set.""" # Remember the directory in which the execution will occur. self.__dir = dir # The path to the executable is the first argument, if not # explicitly specified. if not path: path = arguments[0] # Normalize the path name. At the conclusion of this # processing, the path is either an absolute path, or contains # no directory seperators. if os.path.isabs(path): # An absolute path. pass elif (os.sep in path or (os.altsep and os.altsep in path)): # A relative path name, like "./program". if dir: path = os.path.normpath(os.path.join(dir, path)) if not os.path.isabs(path): path = os.path.abspath(path) else: path = os.path.abspath(path) else: # A path with no directory separators. The program to # execute will be found by searching the PATH environment # variable. pass # Initialize the parent. startupinfo = self._InitializeParent() # Initialize self.__child so that if "fork" or "CreateProcess" # throws an exception our caller can tell that there is no # child process to kill. self.__child = None if sys.platform == "win32": # Compute the command line. The Windows API uses a single # string as the command line, rather than an array of # arguments. command_line = self.__CreateCommandLine(arguments) # If the path is not absolute, then we need to search the # PATH. Since CreateProcess only searches the PATH if its # first argument is None, we clear path here. if not os.path.isabs(path): path = None # Windows supports wide-characters in the environment, but # the Win32 extensions to Python require that all of the # entries in the environment be of the same type, # i.e,. that either all of them be of type StringType or # of type UnicodeType. Therefore, if we find any elements # that are Unicode strings, convert all of them to Unicode # strings. if environment is not None: # See if there any Unicode strings in the environment. uses_unicode = 0 for (k, v) in environment.iteritems(): if (isinstance(k, unicode) or isinstance(v, unicode)): uses_unicode = 1 break # If there are Unicode strings in the environment, # convert all of the key-value pairs to Unicode. if uses_unicode: new_environment = {} for (k, v) in environment.iteritems(): new_environment[unicode(k)] = unicode(v) environment = new_environment # Create the child process. self.__child \ = win32process.CreateProcess(path, command_line, None, None, 1, 0, environment, self.__dir, startupinfo)[0] else: # Fork. self.__child = os.fork() if self.__child == 0: try: # Close the read end of the pipe. if exception_pipe: os.close(exception_pipe[0]) # Initialize the child. self._InitializeChild() # Exec the program. if environment: os.execvpe(path, arguments, environment) else: os.execvp(path, arguments) except: if exception_pipe: # Get the exception information. exc_info = sys.exc_info() # Write it to the pipe. The traceback object # cannot be pickled, unfortunately, so we # cannot communicate that information. cPickle.dump(exc_info[:2], os.fdopen(exception_pipe[1], "w"), 1) # Exit without running cleanups. os._exit(1) # This code should never be reached. assert None # Nothing will be written to the exception pipe in the parent. if exception_pipe: os.close(exception_pipe[1]) # Let the parent take any actions required after creating the # child. self._HandleChild() return self.__child def Run(self, arguments=[], environment = None, dir = None, path = None): """Spawn the program and wait for it to finish. 'arguments' -- The sequence of arguments that should be passed to the executable. The first argument provided in this sequence will be 'argv[0]'. 'environment' -- If not 'None', a dictionary giving the environment that should be provided to the child. If 'None', the child will inherit the parents environment. 'dir' -- If not 'None', the directory in which the child should begin execution. If 'None', the child will execute in the same directory as the parent. 'path' -- If not 'None', the path to the program to run. If 'None', 'arguments[0]' is used. returns -- The status returned by the program. Under UNIX, this is the value returned by 'waitpid'; under Windows, it is the value returned by 'GetExitCodeProcess'. After invoking 'Spawn', this function invokes '_DoParent' to allow the parent process to perform whatever actions are required. After that function returns, the parent waits for the child process to exit.""" # If fork succeeds, but the exec fails, we want information # about *why* it failed. The exit code from the subprocess is # not nearly as illuminating as the exception raised by exec. # Therefore, we create a pipe between the parent and child; # the child writes the exception into the pipe to communicate # it to the parent. if sys.platform != "win32": exception_pipe = os.pipe() # Mark the write end as close-on-exec so that the file # descriptor is not passed on to the child. qm.common.close_file_on_exec(exception_pipe[1]) else: exception_pipe = None # Start the program. child = self.Spawn(arguments, environment, dir, path, exception_pipe) # Give the parent a chance to do whatever it needs to do. self._DoParent() # Wait for the child to exit. if sys.platform == "win32": win32event.WaitForSingleObject(child, win32event.INFINITE) # Get its exit code. return win32process.GetExitCodeProcess(child) else: status = os.waitpid(child, 0)[1] # See if an exception was pushed back up the pipe. data = os.fdopen(exception_pipe[0]).read() # If any data was read, then it is data corresponding to # the exception thrown by exec. if data: # Unpickle the data. exc_info = cPickle.loads(data) # And raise it here. raise exc_info[0], exc_info[1] return status def _InitializeParent(self): """Initialize the parent process. Before spawning the child, this method is invoked to give the parent a chance to initialize itself. returns -- Under Windows, a 'PySTARTUPINFO' structure explaining how the child should be initialized. On other systems, the return value is ignored.""" if sys.platform == "win32": return win32process.STARTUPINFO() def Kill(self): """Kill the child process. The child process is killed in a way that does not permit an orderly shutdown. In other words, 'SIGKILL' is used under UNIX, not 'SIGTERM'. On Windows, 'TerminateProcess' is used, and the exit code from the child process will be '1'.""" if sys.platform == "win32": win32process.TerminateProcess(self._GetChildPID(), 1) else: os.kill(self._GetChildPID(), signal.SIGKILL) def _HandleChild(self): """Run in the parent process after the child has been created. The child process has been spawned; its PID is avialable via '_GetChildPID'. Take any actions in the parent that are required now that the child exists. Derived class versions must call this method.""" pass def _InitializeChild(self): """Initialize the child process. After 'fork' is called this method is invoked to give the child a chance to initialize itself. '_InitializeParent' will already have been called in the parent process. This method is not used under Windows.""" assert sys.platform != "win32" # The way Python's threading support works, every thread except # the main thread always has all signals blocked. This is fine # for the threads themselves, but it causes problems if we # 'fork' from a child thread; the new process starts with all # signals blocked, which is probably not what you want! # Arguably this is a bug in Python, but for the meantime, work # around this by setting the new process's signal mask to match # the signal mask that QMTest was started with. qm.sigmask.restore_mask() if self.__dir: os.chdir(self.__dir) def _DoParent(self): """Perform actions required in the parent after 'Spawn'.""" pass def _GetChildPID(self): """Return the process ID for the child process. returns -- The process ID for the child process. (On Windows, the value returned is the process handle.) Returns 'None' if the child has not yet been created, or if something went awry when creating it. For example, if 'os.fork' throws an exception, this value will return 'None'.""" return self.__child def __CreateCommandLine(self, arguments): """Return a string giving the process command line. arguments -- A sequence of arguments (including argv[0]) indicating the command to be run. returns -- A string that could be provided to the shell in order to run the command.""" command = "" need_space = 0 for a in arguments: # Add a space between arguments. if need_space: command += " " else: need_space = 1 # If the argument contains whitespace characters, enclose # it in quotes. Similarly, an empty argument must be # enclosed in quotes. if not a: command += '""' continue whitespace = 0 for c in string.whitespace: if c in a: whitespace = 1 break if whitespace: command += '"' + a + '"' else: command += a return command class TimeoutExecutable(Executable): """A 'TimeoutExecutable' runs for a limited time. If the timer expires, the child process is killed and self.timedout is set to 1. Otherwise, self.timedout is set to 0. In order to implement this functionality under UNIX, the child process is placed into its own process group. An additional monitoring process is created whose sole job is to kill the primary child's process group if the timeout expires. Process groups are used so that if the child process spawns additional processes they are killed too. A separate monitoring process is used so as not to block the parent. Under Windows, a monitoring thread is created. When the timer expires, the child process is terminated. However, the child process is not placed into a separate process group, so granchildren kare not terminated. In the future, when Python provides access to 'CreateJobObject' and related functions, jobs will be used to provide functionality similar to UNIX process groups. The 'Run' method will automatically start the monitoring process. The 'Spawn' method does not start the monitoring process. User's of 'Spawn' should invoke '_DoParent' in order to start the monitoring process. Derived class '_DoParent' functions should call the version defined in this class.""" def __init__(self, timeout = -1): """Construct a new 'TimeoutExecutable'. 'timeout' -- The number of seconds that the child is permitted to run. This value may be a floating-point value. However, the value may be rounded to an integral value on some systems. Once the timeout expires, the child and its entire process group is killed. (The processes in the process group are sent the 'SIGKILL' signal.) If the 'timeout' is -2, the child is allowed to run forever, but when it terminates the child's process group is killed. If the 'timeout' is -1, this class behaves exactly like 'Executable'.""" super(TimeoutExecutable, self).__init__() self.__timeout = float(timeout) def _InitializeChild(self): # Put the child into its own process group. This step is # performed in both the parent and the child; therefore both # processes can safely assume that the creation of the process # group has taken place. if self.__UseSeparateProcessGroupForChild(): os.setpgid(0, 0) super(TimeoutExecutable, self)._InitializeChild() def _HandleChild(self): super(TimeoutExecutable, self)._HandleChild() if self.__UseSeparateProcessGroupForChild(): # Put the child into its own process group. This step is # performed in both the parent and the child; therefore both # processes can safely assume that the creation of the process # group has taken place. child_pid = self._GetChildPID() try: os.setpgid(child_pid, child_pid) except: # The call to setpgid may fail if the child has exited, # or has already called 'exec'. In that case, we are # guaranteed that the child has already put itself in the # desired process group. pass # Create the monitoring process. # # If the monitoring process is in parent's process group and # kills the child after waitpid has returned in the parent, we # may end up trying to kill a process group other than the one # that we intend to kill. Therefore, we put the monitoring # process in the same process group as the child; that ensures # that the process group will persist until the monitoring # process kills it. self.__monitor_pid = os.fork() if self.__monitor_pid != 0: # Make sure that the monitoring process is placed into the # child's process group before the parent process calls # 'waitpid'. In this way, we are guaranteed that the process # group as the child os.setpgid(self.__monitor_pid, child_pid) else: # Put the monitoring process into the child's process # group. We know the process group still exists at # this point because either (a) we are in the process # group, or (b) the parent has not yet called waitpid. os.setpgid(0, child_pid) # Close all open file descriptors. They are not needed # in the monitor process. Furthermore, when the parent # closes the write end of the stdin pipe to the child, # we do not want the pipe to remain open; leaving the # pipe open in the monitor process might cause the child # to block waiting for additional input. try: max_fds = os.sysconf("SC_OPEN_MAX") except: max_fds = 256 for fd in xrange(max_fds): try: os.close(fd) except: pass try: if self.__timeout >= 0: # Give the child time to run. time.sleep (self.__timeout) # Kill all processes in the child process group. os.kill(0, signal.SIGKILL) else: # This call to select will never terminate. select.select ([], [], []) finally: # Exit. This code is in a finally clause so that # we are guaranteed to get here no matter what. os._exit(0) elif self.__timeout >= 0 and sys.platform == "win32": # Create a monitoring thread. self.__monitor_thread = Thread(target = self.__Monitor) self.__monitor_thread.start() def Run(self, arguments=[], environment = None, dir = None, path = None): if self.__UseSeparateProcessGroupForChild(): self.__monitor_pid = None elif self.__timeout >= 0 and sys.platform == "win32": self.__monitor_thread = None # Run the process. try: status = super(TimeoutExecutable, self).Run(arguments, environment, dir, path) finally: if self.__UseSeparateProcessGroupForChild(): # Clean up the monitoring program; it is no longer needed. child_pid = self._GetChildPID() if child_pid is not None: os.kill(-child_pid, signal.SIGKILL) if self.__monitor_pid is not None: os.waitpid(self.__monitor_pid, 0) elif self.__timeout >= 0 and sys.platform == "win32": # Join the monitoring thread. if self.__monitor_thread is not None: self.__monitor_thread.join() return status def __UseSeparateProcessGroupForChild(self): """Returns true if the child wil be placed in its own process group. returns -- True if the child will be placed in its own process group. In that case, a separate monitoring process will also be created.""" if sys.platform == "win32": # In Windows 2000 (or later), we should use "jobs" by # analogy with UNIX process groups. However, that # functionality is not (yet) provided by the Python Win32 # extensions. return 0 return self.__timeout >= 0 or self.__timeout == -2 if sys.platform == "win32": def __Monitor(self): """Kill the child if the timeout expires. This function is run in the monitoring thread.""" # The timeout may be expressed as a floating-point value # on UNIX, but it must be an integer number of # milliseconds when passed to WaitForSingleObject. timeout = int(self.__timeout * 1000) # Wait for the child process to terminate or for the # timer to expire. result = win32event.WaitForSingleObject(self._GetChildPID(), timeout) # If the timeout occurred, kill the child process. if result == win32con.WAIT_TIMEOUT: self.Kill() class RedirectedExecutable(TimeoutExecutable): """A 'RedirectedExecutable' redirects the standard I/O streams.""" def _InitializeParent(self): super(RedirectedExecutable, self)._InitializeParent() # Create a pipe for each of the streams. self._stdin_pipe = self._StdinPipe() self._stdout_pipe = self._StdoutPipe() self._stderr_pipe = self._StderrPipe() # There has been no output yet. self.stdout = "" self.stderr = "" # Under Windows, create a startupinfo structure that explains # where the streams connected to the child should go. if sys.platform == "win32": # Create a startupinfo structure. startupinfo = win32process.STARTUPINFO() # Indicate that the child process should use the standard # handles in startupinfo. startupinfo.dwFlags = win32con.STARTF_USESTDHANDLES # Attach each of the pipes to the appropriate entries in # startupinfo. Also create a non-inheritable duplicate of the # pipe end we will be using, and close the inheritable # version. if self._stdin_pipe: startupinfo.hStdInput = self._stdin_pipe[0] self._stdin_pipe[1] \ = self.__UninheritableHandle(self._stdin_pipe[1]) else: startupinfo.hStdInput = win32file.INVALID_HANDLE_VALUE if self._stdout_pipe: startupinfo.hStdOutput = self._stdout_pipe[1] self._stdout_pipe[0] \ = self.__UninheritableHandle(self._stdout_pipe[0]) else: startupinfo.hStdOutput = win32file.INVALID_HANDLE_VALUE if self._stderr_pipe: startupinfo.hStdError = self._stderr_pipe[1] self._stderr_pipe[0] \ = self.__UninheritableHandle(self._stderr_pipe[0]) elif self._stdout_pipe: # If there's no stderr pipe -- but there is a stdout # pipe -- redirect both stdout and stderr to the same # pipe. startupinfo.hStdError = self._stdout_pipe[1] else: startupinfo.hStdError = win32file.INVALID_HANDLE_VALUE return startupinfo def _InitializeChild(self): # Let the base class do any initialization required. super(RedirectedExecutable, self)._InitializeChild() # Redirect the standard I/O streams to the pipes. Python does # not provide STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO, # so we must use the file descriptor numbers directly. if self._stdin_pipe: os.dup2(self._stdin_pipe[0], 0) else: os.close(0) if self._stdout_pipe: os.dup2(self._stdout_pipe[1], 1) else: os.close(1) if self._stderr_pipe: os.dup2(self._stderr_pipe[1], 2) elif self._stdout_pipe: # If there's no stderr pipe -- but there is a stdout # pipe -- redirect both stdout and stderr to the same # pipe. os.dup2(self._stdout_pipe[1], 2) else: os.close(2) # Close the pipe fds. This should happen automatically when we # exec the new process anyway, but it is polite to close fds as # soon as possible. if self._stdin_pipe: os.close(self._stdin_pipe[0]) os.close(self._stdin_pipe[1]) if self._stdout_pipe: os.close(self._stdout_pipe[0]) os.close(self._stdout_pipe[1]) if self._stderr_pipe: os.close(self._stderr_pipe[0]) os.close(self._stderr_pipe[1]) def _HandleChild(self): # Close the pipe ends that we do not need. if self._stdin_pipe: self._ClosePipeEnd(self._stdin_pipe[0]) if self._stdout_pipe: self._ClosePipeEnd(self._stdout_pipe[1]) if self._stderr_pipe: self._ClosePipeEnd(self._stderr_pipe[1]) # The pipes created by 'RedirectedExecutable' must be closed # before the monitor process (created by 'TimeoutExecutable') # is created. Otherwise, if the child process dies, 'select' # in the parent will not return if the monitor process may # still have one of the file descriptors open. super(RedirectedExecutable, self)._HandleChild() def _DoParent(self): super(RedirectedExecutable, self)._DoParent() # Process the various redirected streams until none of the # streams remain open. if sys.platform != "win32": while 1: # Prepare the lists of interesting descriptors. read_fds = [] write_fds = [] if self._stdout_pipe: read_fds.append(self._stdout_pipe[0]) if self._stderr_pipe: read_fds.append(self._stderr_pipe[0]) if self._stdin_pipe: write_fds.append(self._stdin_pipe[1]) # If there are no longer any interesting descriptors, we are # done. if not read_fds and not write_fds: return # See which descriptors are ready for processing. read_ready, write_ready \ = select.select(read_fds, write_fds, [])[:2] # Process them. if self._stdout_pipe and self._stdout_pipe[0] in read_ready: self._ReadStdout() if self._stderr_pipe and self._stderr_pipe[0] in read_ready: self._ReadStderr() if self._stdin_pipe and self._stdin_pipe[1] in write_ready: self._WriteStdin() else: # Under Windows, neither select, nor # WaitForMultipleObjects, works on pipes. The only # approach that is reliable under all versions of Windows # is to use a separate thread for each handle. By # converting the pipe ends from OS handles to file # descriptors at this point, _ReadStdout, _ReadStderr, and # _WriteStdin can use the same implementations under # Windows that they do under UNIX. if self._stdin_pipe: h = self._stdin_pipe[1] self._stdin_pipe[1] = msvcrt.open_osfhandle(h, 0) h.Detach() stdin_thread = Thread(target = self.__CallUntilNone, args = (self._WriteStdin, "_stdin_pipe")) else: stdin_thread = None if self._stdout_pipe: h = self._stdout_pipe[0] self._stdout_pipe[0] = msvcrt.open_osfhandle(h, 0) h.Detach() stdout_thread = Thread(target = self.__CallUntilNone, args = (self._ReadStdout, "_stdout_pipe")) else: stdout_thread = None if self._stderr_pipe: h = self._stderr_pipe[0] self._stderr_pipe[0] = msvcrt.open_osfhandle(h, 0) h.Detach() stderr_thread = Thread(target = self.__CallUntilNone, args = (self._ReadStderr, "_stderr_pipe")) else: stderr_thread = None # Start the threads. for t in stdin_thread, stdout_thread, stderr_thread: if t: t.start() # Wait for them to finish. for t in stdin_thread, stdout_thread, stderr_thread: if t: t.join() def _ReadStdout(self): """Read from the standard output pipe.""" # Read some data. data = os.read(self._stdout_pipe[0], 64 * 1024) if not data: # If there is no new data, end-of-file has been reached. os.close(self._stdout_pipe[0]) self._stdout_pipe = None else: # Otherwise, add the data to the output we have already # collected. self.stdout += data def _ReadStderr(self): """Read from the standard error pipe.""" # Read some data. data = os.read(self._stderr_pipe[0], 64 * 1024) if not data: # If there is no new data, end-of-file has been reached. os.close(self._stderr_pipe[0]) self._stderr_pipe = None else: # Otherwise, add the data to the output we have already # collected. self.stderr += data def _WriteStdin(self): """Write to the standard input pipe. This implementation writes no data and closes the pipe.""" # Close the pipe. os.close(self._stdin_pipe[1]) self._stdin_pipe = None def _StdinPipe(self): """Return a pipe to which to redirect the standard input. returns -- A pipe, or 'None' if the standard input should be closed in the child.""" pipe = self._CreatePipe() if sys.platform != "win32": # Make sure that writing to the pipe will never result in # deadlock. fcntl.fcntl(pipe[1], fcntl.F_SETFL, fcntl.fcntl(pipe[1], fcntl.F_GETFL) | os.O_NONBLOCK) return pipe def _StdoutPipe(self): """Return a pipe to which to redirect the standard output. returns -- A pipe, or 'None' if the standard output should be closed in the child.""" return self._CreatePipe() def _StderrPipe(self): """Return a pipe to which to redirect the standard input. returns -- A pipe, or 'None'. If 'None' is returned, but '_StdoutPipe' returns a pipe, then the standard error and standard input will both be redirected to that pipe. However, if '_StdoutPipe' also returns 'None', then the standard error will be closed in the child.""" return self._CreatePipe() def _ClosePipeEnd(self, fd): """Close the file descriptor 'fd', which is one end of a pipe. 'fd' -- Under UNIX, a file descriptor. Under Windows, a handle.""" if sys.platform == "win32": fd.Close() else: os.close(fd) def _CreatePipe(self): """Return a new pipe. returns -- A tuple (under UNIX) or list (under Windows) consisting of the file descriptors (UNIX) or handles (Windows) for the read end and write end of a new pipe. The pipe is inheritable by child processes. On UNIX the fds will not be inherited across 'exec'.""" if sys.platform == "win32": # Create a security descriptor so that we can mark the handles # as inheritable. (A call to os.pipe under Windows # returns handles that are not inheritable.) sa = pywintypes.SECURITY_ATTRIBUTES() sa.bInheritHandle = 1 # Transform the tuple returned into a list so that the # individual elements can be altered. r, w = win32pipe.CreatePipe(sa, 0) return [r, w] else: pipe = os.pipe() for fd in pipe: qm.common.close_file_on_exec(fd) return pipe def __CallUntilNone(self, f, attribute): """Call 'f' until 'self.attribute' is 'None'. 'f' -- A callable. 'attribute' -- A string giving the name of an attribute.""" while getattr(self, attribute) is not None: f() def __UninheritableHandle(self, handle): """Return a duplicate of a file handle that is not inheritable. 'handle' -- A file handle. returns -- A new handle that is a non-inheritable duplicate of the 'handle'. This method should only be used under Windows.""" assert sys.platform == "win32" current_process = win32api.GetCurrentProcess() return win32api.DuplicateHandle(current_process, handle, current_process, 0, 0, win32con.DUPLICATE_SAME_ACCESS) class Filter(RedirectedExecutable): """A 'FilterExecutable' feeds an input string to another proces. The input string is provided to a child process via a pipe; the standard output and standard error streams from the child process are collected in the 'Filter'.""" def __init__(self, input, timeout = -1): """Create a new 'Filter'. 'input' -- The string containing the input to provide to the child process. 'timeout' -- As for 'TimeoutExecutable.__init__'.""" super(Filter, self).__init__(timeout) self.__input = input self.__next = 0 def _WriteStdin(self): # If there's nothing more to write, stop. if self.__next == len(self.__input): super(Filter, self)._WriteStdin() else: # Write some data. self.__next += os.write(self._stdin_pipe[1], self.__input[self.__next : self.__next + 64 * 1024]) ######################################################################## # Variables ####################################################################### __all__ = ["Executable", "TimeoutExecutable", "RedirectedExecutable", "Filter"] qmtest-2.4.1/qm/label.py0000664000076400007640000001372611107032237014442 0ustar stefanstefan######################################################################## # # File: label.py # Author: Alex Samuel # Date: 2001-03-17 # # Contents: # Label # # Copyright (c) 2001, 2002 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from __future__ import nested_scopes import os import re import string import types ######################################################################## # Classes ######################################################################## class Label: """A 'Label' identifies an entity. A 'Label' is a generalization of a filename. Like filenames, labels consist of one or more directories followed by a basename. However, the format used for a label need not be the same as that used by filenames. Each label class defines a separator character to take the place of the '/' character used by many file systems. All labels are relative labels; no label may begin with a separator character.""" def __init__(self, label): """Construct a new 'Label'. 'label' -- A string giving the value of the label.""" assert type(label) in (types.StringType, types.UnicodeType) self._label = label def Join(self, *labels): """Combine this label and the 'labels' into a single label. 'labels' -- A sequence of strings giving the components of the new label. All but the last are taken as directory names; the last is treated as a basename.""" result = self._label for l in labels: if not result: # If the label is empty so far, l is the first component. result = l elif result and result[-1] == self._sep: # If the label thus far ends with a separator, we do not # want to add another one. result += l else: result = result + self._sep + l return self.__class__(result) def Split(self): """Split the label into a pair '(directory, basename)'. returns -- A pair '(directory, basename)', each of which is a label. It is always true that 'directory.join(basename)' will return a label equivalent to the original label.""" last_sep = self._label.rfind(self._sep) if last_sep != -1: return (self.__class__(self._label[:last_sep]), self.__class__(self._label[last_sep + 1:])) else: return (self.__class__(""), self.__class__(self._label)) def SplitLeft(self): """Split the label into a pair '(parent, subpath)'. This is the same operation as Split, except the split occurs at the leftmost separator, not the rightmost. returns -- A pair '(directory, basename)', each of which is a label. It is always true that 'directory.join(basename)' will return a label equivalent to the original label.""" first_sep = self._label.find(self._sep) if first_sep != -1: return (self.__class__(self._label[:first_sep]), self.__class__(self._label[first_sep + 1:])) else: return (self.__class__(self._label), self.__class__("")) def Basename(self): """Return the basename for the label. returns -- A string giving the basename for the label. The value returned for 'l.basename()' is always the same as 'l.split()[1]'.""" return self.Split()[1] def Dirname(self): """Return the directory name for the 'label'. returns -- A string giving the directory name for the 'label'. The value returned for 'l.dirname()' is always the same as 'l.split()[0]'.""" return self.Split()[0] def IsValid(self, label, is_component): """Returns true if 'label' is valid. 'label' -- The string being tested for validity. 'is_component' -- True if the string being tested is just a single component of a label path. returns -- True if 'label' is not valid.""" if label and label[0] == self._sep: # All labels are relative; a valid label cannot begin with a # separator. return 0 elif is_component and self._sep in label: # A component label cannot contain a separator. return 0 elif label.find(self._sep + self._sep) != -1: # It is invalid to have two separators in a row. return 0 return 1 def __str__(self): """Return the string form of this label.""" return self._label ######################################################################## # Functions ######################################################################## __thunk_regex = re.compile("[^a-z0-9_]") def thunk(label): """Sanitize and convert 'label' to a valid label. Makes a best-effort attempt to keep 'label' recognizable during the conversion. returns -- A valid label.""" # Strip leading and trailing whitespace. label = string.strip(label) # Lower capital letters. label = string.lower(label) # Replace all invalid characters with underscores. label = string.replace(label, "+", "x") label = __thunk_regex.sub("_", label) # Trim leading underscores. while len(label) > 0 and label[0] == "_": label = label[1:] # Make sure the label isn't empty. if label == "": raise ValueError, "Empty label" return label ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/qm/db.py0000664000076400007640000000722211107032237013742 0ustar stefanstefan######################################################################## # # File: db.py # Author: Nathaniel Smith 0 and len(self.queue) == self.maxsize # Put a new item in the queue def _put(self, item): self.queue.append(item) # Get an item from the queue def _get(self): item = self.queue[0] del self.queue[0] return item qmtest-2.4.1/qmdist/0000775000076400007640000000000011122067201013660 5ustar stefanstefanqmtest-2.4.1/qmdist/__init__.py0000664000076400007640000000000011107032170015757 0ustar stefanstefanqmtest-2.4.1/qmdist/command/0000775000076400007640000000000011122067201015276 5ustar stefanstefanqmtest-2.4.1/qmdist/command/build_doc.pyc0000664000076400007640000002326211122066673017760 0ustar stefanstefan z Ic @s ddklZddklZlZddklZlZddkl Z l Z ddk l Z l Z ddkZddkZddkTdeifd YZd eifd YZd eifd YZdeifdYZdeifdYZdd d ddgZdS(i(tbuild(tspawntfind_executable(tnewert newer_group(t copy_treet remove_tree(t copy_filet move_fileN(t*tbuild_html_tutorialcBseZdZdZdZRS(s1Defines the procedure to build the html tutorial.sbuild html tutorialc Cstiitii|id}ti}g}dddddgD]}|tii|qJ~}td}|p"|id|id d Sn|i|ti |t |d o|i d tii d ot d n|id |idddd|d|dg}|i di|t|t|ddn|d}td |ot|ttd |nti |d S(s9Run this command, i.e. do the actual document generation.tdocsdoc/tutorial.xmlsdoc/concepts.xmlsdoc/cli_reference.xmlsdoc/customizing.xmlsdoc/extending.xmltxsltprocscould not find xsltproc in PATHscannot build html tutorialNs html/tutorialsbuilding html tutorials tutorial/htmls --novalids --xincludes-oshtml/tutorial/s /doc/html.xsls/doc/tutorial.xmlt s /doc/cs.cssshtml/tutorial/cs.csss/share/doc/qmtest/html/tutorial(tostpathtabspathtjoint build_temptgetcwdRtwarntmkpathtchdirRtannouncetisdirRtsplitRRRtrmtreetTrueR( tselfttempdirtsrcdirt_[1]tpt source_filesR tcmdtdest((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pytruns>$ )      !    (t__name__t __module__t__doc__t descriptionR$(((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pyR stbuild_pdf_tutorialcBseZdZdZdZRS(s0Defines the procedure to build the pdf tutorial.sbuild pdf tutorialc Cstiitii|id}ti}g}dddddgD]}|tii|qJ~}td}d }t}t} |p"|i d|i d d Sntd }|o|d 7}t }n|ptd }t } n|p%td}|o|d7}q#n|p"|i d|i dd Sn|i |ti |t |do|id|i d|idddd|d|dg} |idi| t| |o|idg} n;| o|iddg} n|idddg} |idi| t| |i |dn|d} td| otd| nti |d S(s9Run this command, i.e. do the actual document generation.R sdoc/tutorial.xmlsdoc/concepts.xmlsdoc/cli_reference.xmlsdoc/customizing.xmlsdoc/extending.xmlR scould not find xsltproc in PATHscannot build tutorialNtxeps --stringparam xep.extensions 1tfoptxmlroffs --compats5could not find either of xep, fop, or xmlroff in PATHscannot build tutorial.pdfsprint/tutorial.pdfsbuilding pdf tutorialtprints --novalids --xincludes-osprint/tutorial.fos /doc/fo.xsls/doc/tutorial.xmlR s/share/doc/qmtest/prints$/share/doc/qmtest/print/tutorial.pdf(RRRRRRRtNonetFalseRRRRRRRRRR( RRRRR R!R tfoprocR*R+R"R#((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pyR$Msn$ )                    (R%R&R'R(R$(((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pyR)Hstbuild_ref_manualcBs2eZdZdZd d gZdZdZRS( s4Defines the procedure to build API reference manual.sbuild API reference manuals generator=s name of the doc generator to usesargs=s options to pass to the generatorcCs&d|_d|_tii|dS(N(R.t generatortargsRtinitialize_options(R((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pyR4s  cCstiitii|id}ti}|i||i}|ipd}|p!t d}|o d}q~n|p!t d}|o d}qn|p|i dn,|i dt |g|i d gd S( s9Run this command, i.e. do the actual document generation.R ttepydocs-o share/doc/qmtest/html/manualthappydocs-d share/doc/qmtest/html/manuals3could not find either of epydoc or happydoc in PATHsbuilding reference manualtqmN(RRRRRRRR2R3RRRRR(RRRR2R3((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pyR$s"$      N(s generator=Ns name of the doc generator to use(sargs=Ns options to pass to the generator(R%R&R'R(R.t user_optionsR4R$(((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pyR1s   tbuild_man_pagecBseZdZdZdZRS(s,Defines the procedure to build the man page.sbuild man pagecCs|idtd}|p|iddSntd}d}|i||ddd g}d |}|d |d g7}t||otdd |gndS(s9Run this command, i.e. do the actual document generation.sbuilding man pagethelp2manscannot build man pageNtgzipsshare/man/man1s-Ns-ns4QMTest is an automated software test execution tool.s %s/qmtest.1s-osscripts/qmtests-f(RRRRR(RR;R<tman_dirtcommandtoutput((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pyR$s         (R%R&R'R(R$(((s4/home/stefan/work/qmtest/qmdist/command/build_doc.pyR:st build_docc BseZdZdZdddd d!d"d#d$gZddd dgZhdd<dd<d d <dds 0J,Eqmtest-2.4.1/qmdist/command/build_scripts.pyc0000664000076400007640000000275311122066673020704 0ustar stefanstefan )8Ic @sddkZddkZeidjpeid d joddklZnMddklZddklZddk l Z l Z defdYZdS( iNtposixi(t build_scripts(tST_MODE(tjointnormpathRcBseZdZdZRS(sBuild scripts required for installation. Extend the default build_scripts command as that ommitted to make the scripts executable.cCsti|x|iD]}tii|itii|}|io|i d|qti |t t dd@}|t ddBt dd@}||jo1|i d|||ffti ||qqWdS(Nschanging mode of %st7777it555s!changing mode of %s from %o to %o(tbasetruntscriptstostpathRt build_dirtbasenametdry_runtannouncetstatRtinttchmod(tselftstscripttoldmodetnewmode((s8/home/stefan/work/qmtest/qmdist/command/build_scripts.pyR+s  $    (t__name__t __module__t__doc__R(((s8/home/stefan/work/qmtest/qmdist/command/build_scripts.pyR's(ii( R tsystnamet version_infotdistutils.command.build_scriptsRRRRtos.pathRR(((s8/home/stefan/work/qmtest/qmdist/command/build_scripts.pyss $qmtest-2.4.1/qmdist/command/bdist_wininst.py0000664000076400007640000000204211107032170020526 0ustar stefanstefan######################################################################## # # File: bdist_wininst.py # Author: Stefan Seefeld # Date: 2006-10-30 # # Contents: # command to build windows installer # # Copyright (c) 2006 by CodeSourcery. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from distutils.command.bdist_wininst import bdist_wininst as base import os, os.path ######################################################################## # Classes ######################################################################## class bdist_wininst(base): def initialize_options(self): base.initialize_options(self) self.title = 'QMTest %s'%self.distribution.get_version() self.bitmap = os.path.join('share', 'logo.bmp') self.install_script = 'qmtest-postinstall.py' qmtest-2.4.1/qmdist/command/check.pyc0000664000076400007640000001261011122066673017104 0ustar stefanstefan N+8Ic @sddklZddklZlZddklZlZddkl Z l Z ddk l Z ddk Z ddkZ ddkZddkZe iiZdZdefd YZdS( i(tCommand(tspawntfind_executable(tnewert newer_group(t copy_treet remove_tree(t copy_fileNcCs$tii|o ti|dS(N(tostpathtexiststremove(tfile((s0/home/stefan/work/qmtest/qmdist/command/check.pytremove_if_existsstcheckcBszeZdZdZdddddgZdddd gZdZdZdZdZ dZ dZ dZ RS(s0Defines the testing procedure for QMTest itself.srun internal tests on QMTesttserialtssperform serial teststthreadsttsperform threaded testst processestpsperform sub-processed teststrshtrsperform tests over remote-shelltalltasperform all testscCs:d|_d|_d|_d|_d|_d|_dS(Ni(RRRRtNoneRt build_scripts(tself((s0/home/stefan/work/qmtest/qmdist/command/check.pytinitialize_options0s      cCs|idjo6|ip|ip|ip|i o d|_n|io(d|_d|_d|_d|_n|idddS(sCompute what tests to execute. If no option is specified test everything. Else only run the tests that are chosen.itbuildRN(s build_scriptss build_scripts(RRRRRRtset_undefined_options(R((s0/home/stefan/work/qmtest/qmdist/command/check.pytfinalize_options:s9       cCs8|g|ddddtd|g}t|dS(sPerform serial tests.s-Dtteststruns-cs qmtest_path=N(tnormR(Rtqmtesttoptionstcmd((s0/home/stefan/work/qmtest/qmdist/command/check.pyt check_serialJs  c Csttd|ddddddtddd g }t||g|ddd dtdd d t|d d tdg }t|dS(sPerform threaded tests.stests/QMTest/thread_targets-DR s create-targets-as threads=4s-Ttthreadsthread_target.ThreadTargetR!s-csqmtest_path=%ssqmtest_target=%sN(R R"R(RR#R$R%((s0/home/stefan/work/qmtest/qmdist/command/check.pyt check_threadsRs      c Csttd|ddddddtddd g }t||g|ddd dtdd d t|d d tdg }t|dS(sPerform sub-processed tests.stests/QMTest/process_targets-DR s create-targets-as processes=4s-Ttprocesssprocess_target.ProcessTargetR!s-csqmtest_path=%ssqmtest_target=%sN(R R"R(RR#R$R%((s0/home/stefan/work/qmtest/qmdist/command/check.pytcheck_processesbs      c Csttd|ddddddddtdd d g }t|tiid}|g|ddd dtdd d t|d dt|g }t|dS(s"Perform tests over a remote shell.stests/QMTest/rsh_targets-DR s create-targets-ashost=localhostsremote_shell=sshs-TRsrsh_target.RSHTargetR!s-csqmtest_path=%ssqmtest_target=%sN(R R"RRR tabspath(RR#R$R%t abs_target((s0/home/stefan/work/qmtest/qmdist/command/check.pyt check_rshrs        cCs3|id|iid}tiid}|o|iti|}n |i}|tids      qmtest-2.4.1/qmdist/command/build.py0000664000076400007640000000223311107032170016747 0ustar stefanstefan######################################################################## # # File: build.py # Author: Mark Mitchell # Date: 2003-11-23 # # Contents: # Command to create the build files. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from distutils.command.build import build as base from os.path import join, normpath ######################################################################## # Classes ######################################################################## class build(base): """Build files required for installation.""" def run(self): # Do the default actions. base.run(self) # Copy the classes.qmc file. self.copy_file(join ("qm", "test", "classes", "classes.qmc"), join(self.build_lib, "qm", "test", "classes", "classes.qmc")) qmtest-2.4.1/qmdist/command/build.pyc0000664000076400007640000000150311122066673017125 0ustar stefanstefan x4Ic@s@ddklZddklZlZdefdYZdS(i(tbuild(tjointnormpathRcBseZdZdZRS(s&Build files required for installation.cCsEti||itddddt|idddddS(Ntqmttesttclassess classes.qmc(tbasetrunt copy_fileRt build_lib(tself((s0/home/stefan/work/qmtest/qmdist/command/build.pyRs (t__name__t __module__t__doc__R(((s0/home/stefan/work/qmtest/qmdist/command/build.pyRsN(tdistutils.command.buildRRtos.pathRR(((s0/home/stefan/work/qmtest/qmdist/command/build.pyssqmtest-2.4.1/qmdist/command/build_scripts.py0000664000076400007640000000402411116024767020533 0ustar stefanstefan######################################################################## # # File: build_scripts.py # Author: Stefan Seefeld # Date: 2005-01-05 # # Contents: # Command to build the scripts. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import os, sys # The workaround is only needed on posix systems for # python version < 2.3. if os.name != 'posix' or sys.version_info[:2] > (2,2): # The original command is good enough. from distutils.command.build_scripts import build_scripts else: from distutils.command.build_scripts import build_scripts as base from stat import ST_MODE from os.path import join, normpath ######################################################################## # Classes ######################################################################## class build_scripts(base): """Build scripts required for installation. Extend the default build_scripts command as that ommitted to make the scripts executable.""" def run(self): # Do the default actions. base.run(self) # Work around distutils bug (for python > 2.3) # change permissions to executable. for s in self.scripts: script = os.path.join(self.build_dir, os.path.basename(s)) if self.dry_run: self.announce("changing mode of %s"%script) else: oldmode = os.stat(script)[ST_MODE] & int('7777', 8) newmode = (oldmode | int('555', 8)) & int('7777', 8) if newmode != oldmode: self.announce("changing mode of %s from %o to %o"%(script, oldmode, newmode)), os.chmod(script, newmode) qmtest-2.4.1/qmdist/command/check.py0000664000076400007640000001243211116025516016735 0ustar stefanstefan######################################################################## # # File: check.py # Author: Stefan Seefeld # Date: 2003-09-01 # # Contents: # command to run tests on QMTest itself # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## from distutils.cmd import Command from distutils.spawn import spawn, find_executable from distutils.dep_util import newer, newer_group from distutils.dir_util import copy_tree, remove_tree from distutils.file_util import copy_file import os import os.path import string import glob norm = os.path.normpath def remove_if_exists(file): os.path.exists(file) and os.remove(file) class check(Command): """Defines the testing procedure for QMTest itself.""" description = "run internal tests on QMTest" user_options = [('serial', 's', "perform serial tests"), ('threads', 't', "perform threaded tests"), ('processes', 'p', "perform sub-processed tests"), ('rsh', 'r', "perform tests over remote-shell"), ('all', 'a', "perform all tests"), ] boolean_options = ['serial', 'threads', 'processes', 'rsh'] def initialize_options (self): self.serial = 0 self.threads = 0 self.processes = 0 self.rsh = 0 self.all = None self.build_scripts = None def finalize_options (self): """Compute what tests to execute. If no option is specified test everything. Else only run the tests that are chosen.""" if self.all == None and not (self.serial or self.threads or self.processes or self.rsh): self.all = 1 if (self.all): self.serial = 1 self.threads = 1 self.processes = 1 self.rsh = 1 # Pick up the build scripts directory from the 'build' command. self.set_undefined_options("build", ("build_scripts", "build_scripts")) def check_serial(self, qmtest, options): """Perform serial tests.""" cmd = [qmtest] + options + \ ['-D', 'tests', 'run', '-c', norm('qmtest_path=' + qmtest)] spawn(cmd) def check_threads(self, qmtest, options): """Perform threaded tests.""" remove_if_exists(norm('tests/QMTest/thread_target')) cmd = [qmtest, '-D', 'tests', 'create-target', '-a', 'threads=4', '-T', norm('tests/QMTest/thread_target'), 'thread', 'thread_target.ThreadTarget'] spawn(cmd) cmd = [qmtest] + options + \ ['-D', 'tests', 'run', '-T', norm('tests/QMTest/thread_target'), '-c', 'qmtest_path=%s' % norm(qmtest), '-c', 'qmtest_target=%s'%norm('tests/QMTest/thread_target')] spawn(cmd) def check_processes(self, qmtest, options): """Perform sub-processed tests.""" remove_if_exists(norm('tests/QMTest/process_target')) cmd = [qmtest, '-D', 'tests', 'create-target', '-a', 'processes=4', '-T', norm('tests/QMTest/process_target'), 'process', 'process_target.ProcessTarget'] spawn(cmd) cmd = [qmtest] + options + \ ['-D', 'tests', 'run', '-T', norm('tests/QMTest/process_target'), '-c', 'qmtest_path=%s' % norm(qmtest), '-c', 'qmtest_target=%s'%norm('tests/QMTest/process_target')] spawn(cmd) def check_rsh(self, qmtest, options): """Perform tests over a remote shell.""" remove_if_exists(norm('tests/QMTest/rsh_target')) cmd = [qmtest, '-D', 'tests', 'create-target', '-a', 'host=localhost', '-a', 'remote_shell=ssh', '-T', norm('tests/QMTest/rsh_target'), 'rsh', 'rsh_target.RSHTarget'] spawn(cmd) abs_target = os.path.abspath("tests/QMTest/rsh_target") cmd = [qmtest] + options + \ ['-D', 'tests', 'run', '-T', norm('tests/QMTest/rsh_target'), '-c', 'qmtest_path=%s' % norm(qmtest), '-c', 'qmtest_target=%s' % norm(abs_target)] spawn(cmd) def run(self): """Execute the various tests.""" # Ensure that QMTest is already built. self.run_command("build") b = self.distribution.get_command_obj('build') python_path = os.environ.get('PYTHONPATH') if python_path: python_path = b.build_lib + os.pathsep + python_path else: python_path = b.build_lib os.environ['PYTHONPATH'] = python_path qmtest = os.path.abspath(os.path.join(self.build_scripts, 'qmtest')) if "QMTESTFLAGS" in os.environ: options = os.environ["QMTESTFLAGS"].split() else: options = [] if self.serial: self.check_serial(qmtest, options) if self.threads: self.check_threads(qmtest, options) if self.processes: self.check_processes(qmtest, options) if self.rsh: self.check_rsh(qmtest, options) qmtest-2.4.1/qmdist/command/build_py.pyc0000664000076400007640000000232511122066673017640 0ustar stefanstefan x4Ic@sRddklZddklZddkZddkZdefdYZdS(i(tbuild_py(treset_config_variablesNRcBseZdZdZRS(sAdjust config variable to make them valid even during the build. This allows us to run (in particular, test) QMTest after being built, but before being installed.c Csvti|tii|idd}|idt|d|ii dti dtiiddddS( Ntqms config.pysadjusting config parameterstversiontprefixtextension_pathttesttclasses( tbasetruntostpathtjoint build_libtannounceRt distributiont get_versiontgetcwd(tselft config_file((s3/home/stefan/work/qmtest/qmdist/command/build_py.pyR !s     (t__name__t __module__t__doc__R (((s3/home/stefan/work/qmtest/qmdist/command/build_py.pyRs(tdistutils.command.build_pyRRtqmdist.commandRR tsys(((s3/home/stefan/work/qmtest/qmdist/command/build_py.pyssqmtest-2.4.1/qmdist/command/build_doc.py0000664000076400007640000002327311110151172017601 0ustar stefanstefan######################################################################## # # File: build_doc.py # Author: Stefan Seefeld # Date: 2003-09-01 # # Contents: # command to build documentation as an extension to distutils # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## from distutils.command import build from distutils.spawn import spawn, find_executable from distutils.dep_util import newer, newer_group from distutils.dir_util import copy_tree, remove_tree from distutils.file_util import copy_file, move_file import os, os.path from shutil import * class build_html_tutorial(build.build): """Defines the procedure to build the html tutorial.""" description = "build html tutorial" def run(self): """Run this command, i.e. do the actual document generation.""" tempdir = os.path.abspath(os.path.join(self.build_temp, 'doc')) srcdir = os.getcwd() source_files = [os.path.abspath(p) for p in ['doc/tutorial.xml', 'doc/concepts.xml', 'doc/cli_reference.xml', 'doc/customizing.xml', 'doc/extending.xml']] # Look for programs and supporting libraries required to build # DocBook documentation. xsltproc = find_executable('xsltproc') if not xsltproc: self.warn("could not find xsltproc in PATH") self.warn("cannot build html tutorial") return self.mkpath(tempdir) os.chdir(tempdir) if newer_group(source_files, 'html/tutorial'): self.announce("building html tutorial") if os.path.isdir('html/tutorial'): remove_tree('html/tutorial') self.mkpath('tutorial/html') cmd = xsltproc.split() + ['--novalid', '--xinclude', '-o', 'html/tutorial/', srcdir + '/doc/html.xsl', srcdir + '/doc/tutorial.xml'] self.announce(' '.join(cmd)) spawn(cmd) copy_file(srcdir + '/doc/cs.css', 'html/tutorial/cs.css') dest = srcdir + '/share/doc/qmtest/html/tutorial' if newer('html/tutorial', dest): rmtree(dest, True) copy_tree('html/tutorial', dest) os.chdir(srcdir) class build_pdf_tutorial(build.build): """Defines the procedure to build the pdf tutorial.""" description = "build pdf tutorial" def run(self): """Run this command, i.e. do the actual document generation.""" tempdir = os.path.abspath(os.path.join(self.build_temp, 'doc')) srcdir = os.getcwd() source_files = [os.path.abspath(p) for p in ['doc/tutorial.xml', 'doc/concepts.xml', 'doc/cli_reference.xml', 'doc/customizing.xml', 'doc/extending.xml']] # Look for programs and supporting libraries required to build # DocBook documentation. xsltproc = find_executable('xsltproc') foproc = None xep = False fop = False if not xsltproc: self.warn("could not find xsltproc in PATH") self.warn("cannot build tutorial") return foproc = find_executable('xep') if foproc: xsltproc += ' --stringparam xep.extensions 1' xep = True if not foproc: foproc = find_executable('fop') fop = True if not foproc: foproc = find_executable('xmlroff') if foproc: foproc += ' --compat' if not foproc: self.warn("could not find either of xep, fop, or xmlroff in PATH") self.warn("cannot build tutorial.pdf") return self.mkpath(tempdir) os.chdir(tempdir) if newer_group(source_files, 'print/tutorial.pdf'): self.announce("building pdf tutorial") self.mkpath('print') cmd = xsltproc.split() + ['--novalid', '--xinclude', '-o', 'print/tutorial.fo', srcdir + '/doc/fo.xsl', srcdir + '/doc/tutorial.xml'] self.announce(' '.join(cmd)) spawn(cmd) if xep: cmd = foproc.split() + ['print/tutorial.fo'] elif fop: cmd = foproc.split() + ['print/tutorial.fo', 'print/tutorial.pdf'] else: cmd = foproc.split() + ['-o', 'print/tutorial.pdf', 'print/tutorial.fo'] self.announce(' '.join(cmd)) spawn(cmd) self.mkpath(srcdir + '/share/doc/qmtest/print') dest = srcdir + '/share/doc/qmtest/print/tutorial.pdf' if newer('print/tutorial.pdf', dest): copy_file('print/tutorial.pdf', dest) os.chdir(srcdir) class build_ref_manual(build.build): """Defines the procedure to build API reference manual.""" description = "build API reference manual" user_options = [ ("generator=", None, "name of the doc generator to use"), ("args=", None, "options to pass to the generator") ] def initialize_options(self): self.generator = None self.args = None build.build.initialize_options(self) def run(self): """Run this command, i.e. do the actual document generation.""" tempdir = os.path.abspath(os.path.join(self.build_temp, 'doc')) srcdir = os.getcwd() self.mkpath(tempdir) generator = self.generator args = self.args or '' if not generator: generator = find_executable('epydoc') if generator: args = '-o share/doc/qmtest/html/manual' if not generator: generator = find_executable('happydoc') if generator: args = '-d share/doc/qmtest/html/manual' if not generator: self.warn("could not find either of epydoc or happydoc in PATH") else: self.announce("building reference manual") spawn([generator] + args.split() + ['qm']) class build_man_page(build.build): """Defines the procedure to build the man page.""" description = "build man page" def run(self): """Run this command, i.e. do the actual document generation.""" self.announce("building man page") help2man = find_executable('help2man') if not help2man: self.warn("cannot build man page") return gzip = find_executable('gzip') man_dir = 'share/man/man1' self.mkpath(man_dir) command = [help2man, '-N', '-n', 'QMTest is an automated software test execution tool.'] output = '%s/qmtest.1'%man_dir command += ['-o', output, 'scripts/qmtest'] spawn(command) if gzip: spawn(['gzip', '-f', output]) class build_doc(build.build): """Defines the specific procedure to build QMTest's documentation. As this command is only ever used on 'posix' platforms, no effort has been made to make this code portable to other platforms such as 'nt'.""" description = "build documentation" user_options = [ ("html", None, "generate HTML documentation"), ("no-html", None, "do not generate HTML documentation"), ("pdf", None, "generate PDF documentation"), ("no-pdf", None, "do not generate PDF documentation"), ("ref-manual", None, "generate reference manual"), ("no-ref-manual", None, "do not generate reference manual"), ("man-page", None, "generate man page"), ("no-man-page", None, "do not generate man page"), ] boolean_options = [ "html", "pdf", "ref-manual", "man-page"] negative_opt = { "no-html" : "html", "no-pdf" : "pdf", "no-ref-manual" : "ref-manual", "no-man-page" : "man-page"} def initialize_options(self): self.html = True self.pdf = True self.ref_manual = True self.man_page = True build.build.initialize_options(self) def run(self): """Run this command, i.e. do the actual document generation.""" tempdir = os.path.abspath(os.path.join(self.build_temp, 'doc')) srcdir = os.getcwd() self.mkpath(tempdir) # # Write the version to a file so the tutorial can refer to it. This # file contains exactly the version number -- there must be no # trailing newline, for example. # self.announce("writing version file") f = open(os.path.join(tempdir, 'qm-version'), 'w') f.write(self.distribution.get_version()) f.close() for c in self.get_sub_commands(): self.run_command(c) def build_html_tutorial(self) : return self.html def build_pdf_tutorial(self) : return self.pdf def build_ref_manual(self) : return self.ref_manual def build_man_page(self) : return self.man_page sub_commands = [('build_html_tutorial', build_html_tutorial), ('build_pdf_tutorial', build_pdf_tutorial), ('build_ref_manual', build_ref_manual), ('build_man_page', build_man_page)] __all__ = ['build_html_tutorial', 'build_pdf_tutorial', 'build_ref_manual', 'build_man_page', 'build_doc'] qmtest-2.4.1/qmdist/command/build_py.py0000664000076400007640000000307011107032170017457 0ustar stefanstefan######################################################################## # # File: build_py.py # Author: Stefan Seefeld # Date: 2006-11-03 # # Contents: # Command to build the python modules. # # Copyright (c) 2006 by CodeSourcery. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from distutils.command.build_py import build_py as base from qmdist.command import reset_config_variables import os, sys ######################################################################## # Classes ######################################################################## class build_py(base): """Adjust config variable to make them valid even during the build. This allows us to run (in particular, test) QMTest after being built, but before being installed.""" def run(self): # Do the default actions. base.run(self) config_file = os.path.join(self.build_lib, 'qm', 'config.py') self.announce("adjusting config parameters") reset_config_variables(config_file, version=self.distribution.get_version(), prefix=os.getcwd(), extension_path=os.path.join('qm', 'test', 'classes')) qmtest-2.4.1/qmdist/command/__init__.py0000664000076400007640000000344011107032170017410 0ustar stefanstefan######################################################################## # # File: __init__.py # Author: Mark Mitchell # Date: 2003-10-14 # # Contents: # Support functions for installation scripts. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import os.path, re ######################################################################## # Functions ######################################################################## def get_relative_path(dir1, dir2): """Return the relative path from 'dir1' to 'dir2'. 'dir1' -- The path to a directory. 'dir2' -- The path to a directory. returns -- The relative path from 'dir1' to 'dir2'.""" dir1 = os.path.abspath(dir1) dir2 = os.path.abspath(dir2) rel_path = "" while not dir2.startswith(dir1): rel_path = os.path.join(os.pardir, rel_path) dir1 = os.path.dirname(dir1) if dir1 == os.sep: dir1 = "" break return os.path.join(rel_path, dir2[len(dir1) + 1:]) def reset_config_variables(config_file, **vars): """Reset specific variables in the given config file to new values. 'config_file' -- The config file to modify. 'vars' -- dict object containing variables to reset, with their new values. """ script = open(config_file, 'r').read() for v in vars: script, found = re.subn('%s=.*'%v,'%s=%s'%(v, repr(vars[v])), script) if not found: script += '%s=%s'%(v, repr(vars[v])) c = open(config_file, 'w') c.write(script) c.close() qmtest-2.4.1/qmdist/command/check.py~0000664000076400007640000001244011107032170017124 0ustar stefanstefan######################################################################## # # File: check.py # Author: Stefan Seefeld # Date: 2003-09-01 # # Contents: # command to run tests on QMTest itself # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## from distutils.cmd import Command from distutils.spawn import spawn, find_executable from distutils.dep_util import newer, newer_group from distutils.dir_util import copy_tree, remove_tree from distutils.file_util import copy_file import os import os.path import string import glob norm = os.path.normpath def remove_if_exists(file): os.path.exists(file) and os.remove(file) class check(Command): """Defines the testing procedure for QMTest itself.""" description = "run internal tests on QMTest" user_options = [('serial', 's', "perform serial tests"), ('threads', 't', "perform threaded tests"), ('processes', 'p', "perform sub-processed tests"), ('rsh', 'r', "perform tests over remote-shell"), ('all', 'a', "perform all tests"), ] boolean_options = ['serial', 'threads', 'processes', 'rsh'] def initialize_options (self): self.serial = 0 self.threads = 0 self.processes = 0 self.rsh = 0 self.all = None self.build_scripts = None def finalize_options (self): """Compute what tests to execute. If no option is specified test everything. Else only run the tests that are chosen.""" if self.all == None and not (self.serial or self.threads or self.processes or self.rsh): self.all = 1 if (self.all): self.serial = 1 self.threads = 1 self.processes = 1 self.rsh = 1 # Pick up the build scripts directory from the 'build' command. self.set_undefined_options("build", ("build_scripts", "build_scripts")) def check_serial(self, qmtest, options): """Perform serial tests.""" cmd = [qmtest] + options + \ ['-D', 'tests', 'run', '-c', norm('qmtest_path=' + qmtest)] spawn(cmd) def check_threads(self, qmtest, options): """Perform threaded tests.""" remove_if_exists(norm('tests/QMTest/thread_target')) cmd = [qmtest, '-D', 'tests', 'create-target', '-a', 'threads=4', '-T', norm('tests/QMTest/thread_target'), 'thread', 'thread_target.ThreadTarget'] spawn(cmd) cmd = [qmtest] + options + \ ['-D', 'tests', 'run', '-T', norm('tests/QMTest/thread_target'), '-c', 'qmtest_path=%s' % norm(qmtest), '-c', 'qmtest_target=%s'%norm('tests/QMTest/thread_target')] spawn(cmd) def check_processes(self, qmtest, options): """Perform sub-processed tests.""" remove_if_exists(norm('tests/QMTest/process_target')) cmd = [qmtest, '-D', 'tests', 'create-target', '-a', 'processes=4', '-T', norm('tests/QMTest/process_target'), 'process', 'process_target.ProcessTarget'] spawn(cmd) cmd = [qmtest] + options + \ ['-D', 'tests', 'run', '-T', norm('tests/QMTest/process_target'), '-c', 'qmtest_path=%s' % norm(qmtest), '-c', 'qmtest_target=%s'%norm('tests/QMTest/process_target')] spawn(cmd) def check_rsh(self, qmtest, options): """Perform tests over a remote shell.""" remove_if_exists(norm('tests/QMTest/rsh_target')) cmd = [qmtest, '-D', 'tests', 'create-target', '-a', 'host=localhost', '-a', 'remote_shell=ssh', '-T', norm('tests/QMTest/rsh_target'), 'rsh', 'rsh_target.RSHTarget'] spawn(cmd) abs_target = os.path.abspath("tests/QMTest/rsh_target") cmd = [qmtest] + options + \ ['-D', 'tests', 'run', '-T', norm('tests/QMTest/rsh_target'), '-c', 'qmtest_path=%s' % norm(qmtest), '-c', 'qmtest_target=%s' % norm(abs_target)] spawn(cmd) def run(self): """Execute the various tests.""" # Ensure that QMTest is already built. self.run_command("build") b = self.distribution.get_command_obj('build') python_path = os.environ.get('PYTHONPATH') if python_path: python_path = b.build_lib + os.pathsep + python_path else: python_path = b.build_lib os.environ['PYTHONPATH'] = python_path qmtest = os.path.abspath(os.path.join(self.build_scripts, 'qmtest')) if os.environ.has_key("QMTESTFLAGS"): options = os.environ["QMTESTFLAGS"].split() else: options = [] if self.serial: self.check_serial(qmtest, options) if self.threads: self.check_threads(qmtest, options) if self.processes: self.check_processes(qmtest, options) if self.rsh: self.check_rsh(qmtest, options) qmtest-2.4.1/qmdist/command/build_doc.py~0000664000076400007640000002046511107032170020001 0ustar stefanstefan######################################################################## # # File: build_doc.py # Author: Stefan Seefeld # Date: 2003-09-01 # # Contents: # command to build documentation as an extension to distutils # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## from distutils.command import build from distutils.spawn import spawn, find_executable from distutils.dep_util import newer, newer_group from distutils.dir_util import copy_tree, remove_tree from distutils.file_util import copy_file, move_file import os, os.path from shutil import * class build_html_tutorial(build.build): """Defines the procedure to build the html tutorial.""" description = "build html tutorial" def run(self): """Run this command, i.e. do the actual document generation.""" tempdir = os.path.abspath(os.path.join(self.build_temp, 'doc')) srcdir = os.getcwd() source_files = [os.path.abspath(p) for p in ['doc/tutorial.xml', 'doc/concepts.xml', 'doc/cli_reference.xml', 'doc/customizing.xml', 'doc/extending.xml']] # Look for programs and supporting libraries required to build # DocBook documentation. xsltproc = find_executable('xsltproc') if not xsltproc: self.warn("could not find xsltproc in PATH") self.warn("cannot build html tutorial") return self.mkpath(tempdir) os.chdir(tempdir) if newer_group(source_files, 'html/tutorial'): self.announce("building html tutorial") if os.path.isdir('html/tutorial'): remove_tree('html/tutorial') self.mkpath('tutorial/html') cmd = xsltproc.split() + ['--novalid', '--xinclude', '-o', 'html/tutorial/', srcdir + '/doc/html.xsl', srcdir + '/doc/tutorial.xml'] self.announce(' '.join(cmd)) spawn(cmd) copy_file(srcdir + '/doc/cs.css', 'html/tutorial/cs.css') dest = srcdir + '/share/doc/qmtest/html/tutorial' if newer('html/tutorial', dest): rmtree(dest, True) copy_tree('html/tutorial', dest) os.chdir(srcdir) class build_pdf_tutorial(build.build): """Defines the procedure to build the pdf tutorial.""" description = "build pdf tutorial" def run(self): """Run this command, i.e. do the actual document generation.""" tempdir = os.path.abspath(os.path.join(self.build_temp, 'doc')) srcdir = os.getcwd() source_files = [os.path.abspath(p) for p in ['doc/tutorial.xml', 'doc/concepts.xml', 'doc/cli_reference.xml', 'doc/customizing.xml', 'doc/extending.xml']] # Look for programs and supporting libraries required to build # DocBook documentation. xsltproc = find_executable('xsltproc') foproc = None xep = False if not xsltproc: self.warn("could not find xsltproc in PATH") self.warn("cannot build tutorial") return foproc = find_executable('xep') if foproc: xsltproc += ' --stringparam xep.extensions 1' xep = True if not foproc: foproc = find_executable('fop') if not foproc: foproc = find_executable('xmlroff') if foproc: foproc += ' --compat' if not foproc: self.warn("could not find either of xep, fop, or xmlroff in PATH") self.warn("cannot build tutorial.pdf") return self.mkpath(tempdir) os.chdir(tempdir) if newer_group(source_files, 'print/tutorial.pdf'): self.announce("building pdf tutorial") self.mkpath('print') cmd = xsltproc.split() + ['--novalid', '--xinclude', '-o', 'print/tutorial.fo', srcdir + '/doc/fo.xsl', srcdir + '/doc/tutorial.xml'] self.announce(' '.join(cmd)) spawn(cmd) if xep: cmd = foproc.split() + ['print/tutorial.fo'] else: cmd = foproc.split() + ['-o', 'print/tutorial.pdf', 'print/tutorial.fo'] self.announce(' '.join(cmd)) spawn(cmd) self.mkpath(srcdir + '/share/doc/qmtest/print') dest = srcdir + '/share/doc/qmtest/print/tutorial.pdf' if newer('print/tutorial.pdf', dest): copy_file('print/tutorial.pdf', dest) os.chdir(srcdir) class build_ref_manual(build.build): """Defines the procedure to build API reference manual.""" description = "build API reference manual" user_options = [ ("generator=", None, "name of the doc generator to use"), ("args=", None, "options to pass to the generator") ] def initialize_options(self): self.generator = None self.args = None build.build.initialize_options(self) def run(self): """Run this command, i.e. do the actual document generation.""" tempdir = os.path.abspath(os.path.join(self.build_temp, 'doc')) srcdir = os.getcwd() self.mkpath(tempdir) generator = self.generator args = self.args or '' if not generator: generator = find_executable('epydoc') if generator: args = '-o share/doc/qmtest/html/manual' if not generator: generator = find_executable('happydoc') if generator: args = '-d share/doc/qmtest/html/manual' if not generator: self.warn("could not find either of epydoc or happydoc in PATH") else: self.announce("building reference manual") spawn([generator] + args.split() + ['qm']) class build_doc(build.build): """Defines the specific procedure to build QMTest's documentation. As this command is only ever used on 'posix' platforms, no effort has been made to make this code portable to other platforms such as 'nt'.""" description = "build documentation" user_options = [ ("html", None, "generate HTML documentation"), ("no-html", None, "do not generate HTML documentation"), ("pdf", None, "generate PDF documentation"), ("no-pdf", None, "do not generate PDF documentation"), ("ref-manual", None, "generate reference manual"), ("no-ref-manual", None, "do not generate reference manual"), ] boolean_options = [ "html", "pdf", "ref-manual" ] negative_opt = { "no-html" : "html", "no-pdf" : "pdf", "no-ref-manual" : "ref-manual" } def initialize_options(self): self.html = True self.pdf = True self.ref_manual = True build.build.initialize_options(self) def run(self): """Run this command, i.e. do the actual document generation.""" tempdir = os.path.abspath(os.path.join(self.build_temp, 'doc')) srcdir = os.getcwd() self.mkpath(tempdir) # # Write the version to a file so the tutorial can refer to it. This # file contains exactly the version number -- there must be no # trailing newline, for example. # self.announce("writing version file") f = open(os.path.join(tempdir, 'qm-version'), 'w') f.write(self.distribution.get_version()) f.close() for c in self.get_sub_commands(): self.run_command(c) def build_html_tutorial(self) : return self.html def build_pdf_tutorial(self) : return self.pdf def build_ref_manual(self) : return self.ref_manual sub_commands = [('build_html_tutorial', build_html_tutorial), ('build_pdf_tutorial', build_pdf_tutorial), ('build_ref_manual', build_ref_manual)] qmtest-2.4.1/qmdist/command/bdist_wininst.pyc0000664000076400007640000000156411122066673020715 0ustar stefanstefan x4Ic@sBddklZddkZddkZdefdYZdS(i(t bdist_wininstNRcBseZdZRS(cCsHti|d|ii|_tiidd|_d|_ dS(Ns QMTest %stshareslogo.bmpsqmtest-postinstall.py( tbasetinitialize_optionst distributiont get_versionttitletostpathtjointbitmaptinstall_script(tself((s8/home/stefan/work/qmtest/qmdist/command/bdist_wininst.pyRs (t__name__t __module__R(((s8/home/stefan/work/qmtest/qmdist/command/bdist_wininst.pyRs(tdistutils.command.bdist_wininstRRRtos.path(((s8/home/stefan/work/qmtest/qmdist/command/bdist_wininst.pyssqmtest-2.4.1/qmdist/command/build_scripts.py~0000664000076400007640000000377111107032170020724 0ustar stefanstefan######################################################################## # # File: build_scripts.py # Author: Stefan Seefeld # Date: 2005-01-05 # # Contents: # Command to build the scripts. # # Copyright (c) 2005 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import os, sys # The workaround is only needed on posix systems for # python version < 2.3. if os.name != 'posix' or sys.version_info[:2] > (2,2): # The original command is good enough. from distutils.command.build_scripts import build_scripts else: from distutils.command.build_scripts import build_scripts as base from stat import ST_MODE from os.path import join, normpath ######################################################################## # Classes ######################################################################## class build_scripts(base): """Build scripts required for installation. Extend the default build_scripts command as that ommitted to make the scripts executable.""" def run(self): # Do the default actions. base.run(self) # Work around distutils bug (for python > 2.3) # change permissions to executable. for s in self.scripts: script = os.path.join(self.build_dir, os.path.basename(s)) if self.dry_run: self.announce("changing mode of %s"%script) else: oldmode = os.stat(script)[ST_MODE] & 07777 newmode = (oldmode | 0555) & 07777 if newmode != oldmode: self.announce("changing mode of %s from %o to %o"%(script, oldmode, newmode)), os.chmod(script, newmode) qmtest-2.4.1/qmdist/command/install_lib.pyc0000664000076400007640000000416411122066673020330 0ustar stefanstefan x4Ic@sVddklZddklZddkZddklZdefdYZdS(i(t install_lib(treset_config_variablesN(tjoinRcBs)eZdZdZdZdZRS(sInstall library files.cCs)ti|}|tddddgS(Ntqmttesttclassess classes.qmc(tbaset get_inputsR(tselftinputs((s6/home/stefan/work/qmtest/qmdist/command/install_lib.pyR scCs/ti|}|t|iddddgS(NRRRs classes.qmc(Rt get_outputsRt install_dir(Rtoutputs((s6/home/stefan/work/qmtest/qmdist/command/install_lib.pyR &s cCs3ti|t|idd}|id|iid}|i}tdddti d }t |d |ii d |d ||g}d d k l }|idi}|io)||ddddd |d|in|idjo5||d|iddd |d|id|indS(NRs config.pysadjusting config parameterstinstalltsharetqmtestssite-extensions-%d.%ditversiontprefixtextension_pathi(t byte_compiletoptimizeitforceitdry_runtverbose(RtrunRR tannouncet distributiontget_command_objRtsyst version_infoRt get_versiontdistutils.utilRtget_finalized_commandtroottcompileRRR(Rt config_filetiRRtfilesRt install_root((s6/home/stefan/work/qmtest/qmdist/command/install_lib.pyR,s,         (t__name__t __module__t__doc__RR R(((s6/home/stefan/work/qmtest/qmdist/command/install_lib.pyRs  (tdistutils.command.install_libRRtqmdist.commandRRtos.pathR(((s6/home/stefan/work/qmtest/qmdist/command/install_lib.pyss qmtest-2.4.1/qmdist/command/install_lib.py0000664000076400007640000000502211107032170020143 0ustar stefanstefan######################################################################## # # File: install_lib.py # Author: Mark Mitchell # Date: 2003-11-23 # # Contents: # Command to install library files. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from distutils.command.install_lib import install_lib as base from qmdist.command import reset_config_variables import sys from os.path import join ######################################################################## # Classes ######################################################################## class install_lib(base): """Install library files.""" def get_inputs(self): inputs = base.get_inputs(self) return inputs + [join("qm", "test", "classes", "classes.qmc")] def get_outputs(self): outputs = base.get_outputs(self) return outputs + [join(self.install_dir, "qm", "test", "classes", "classes.qmc")] def run(self): # Do the standard installation. base.run(self) config_file = join(self.install_dir, 'qm', 'config.py') self.announce("adjusting config parameters") i = self.distribution.get_command_obj('install') prefix = i.prefix extension_path = join('share', 'qmtest', 'site-extensions-%d.%d'%sys.version_info[:2]) reset_config_variables(config_file, version=self.distribution.get_version(), prefix=prefix, extension_path=extension_path) # Make sure the new config file gets recompiled, or else python may # not notice it is in fact different from the original config file. files = [config_file] from distutils.util import byte_compile install_root = self.get_finalized_command('install').root if self.compile: byte_compile(files, optimize=0, force=1, prefix=install_root, dry_run=self.dry_run) if self.optimize > 0: byte_compile(files, optimize=self.optimize, force=1, prefix=install_root, verbose=self.verbose, dry_run=self.dry_run) qmtest-2.4.1/qmdist/command/__init__.pyc0000664000076400007640000000302211122066673017563 0ustar stefanstefan x4Ic@s.ddkZddkZdZdZdS(iNcCstii|}tii|}d}xZ|i|pItiiti|}tii|}|tijo d}Pq-q-Wtii||t|dS(sReturn the relative path from 'dir1' to 'dir2'. 'dir1' -- The path to a directory. 'dir2' -- The path to a directory. returns -- The relative path from 'dir1' to 'dir2'.ti( tostpathtabspatht startswithtjointpardirtdirnametseptlen(tdir1tdir2trel_path((s3/home/stefan/work/qmtest/qmdist/command/__init__.pytget_relative_paths  cKst|di}xj|D]b}tid|d|t||f|\}}|p"|d|t||f7}qqWt|d}|i||idS(sReset specific variables in the given config file to new values. 'config_file' -- The config file to modify. 'vars' -- dict object containing variables to reset, with their new values. trs%s=.*s%s=%stwN(topentreadtretsubntreprtwritetclose(t config_filetvarstscripttvtfoundtc((s3/home/stefan/work/qmtest/qmdist/command/__init__.pytreset_config_variables/s 3- (tos.pathRRR R(((s3/home/stefan/work/qmtest/qmdist/command/__init__.pyss qmtest-2.4.1/qmdist/__init__.pyc0000664000076400007640000000020211122066673016142 0ustar stefanstefan x4Ic@sdS(N((((s+/home/stefan/work/qmtest/qmdist/__init__.pyssqmtest-2.4.1/benchmarks/0000775000076400007640000000000011122067201014474 5ustar stefanstefanqmtest-2.4.1/benchmarks/throughput/0000775000076400007640000000000011122067201016705 5ustar stefanstefanqmtest-2.4.1/benchmarks/throughput/QMTest/0000775000076400007640000000000011122067201020062 5ustar stefanstefanqmtest-2.4.1/benchmarks/throughput/QMTest/classes.qmc0000664000076400007640000000025211107032214022217 0ustar stefanstefan throughput.ThroughputTestthroughput.ThroughputDatabaseqmtest-2.4.1/benchmarks/throughput/QMTest/configuration0000664000076400007640000000024211107032214022651 0ustar stefanstefan 1000 qmtest-2.4.1/benchmarks/throughput/QMTest/throughput.py0000664000076400007640000000366711107032214022660 0ustar stefanstefan######################################################################## # # File: throughput.py # Author: Mark Mitchell # Date: 07/31/2003 # # Contents: # Test datbase for testing execution engine throughput. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.fields import * from qm.test.database import * from qm.test.result import * from qm.test.test import * import random ######################################################################## # Classes ######################################################################## class ThroughputTest(Test): def Run(self, context, result): return class ThroughputDatabase(Database): arguments = [ IntegerField("num_tests", default_value = 100) ] def GetIds(self, kind, directory = "", scan_subdirs = 1): if kind != Database.TEST: return super(ThroughputDatabase, self).GetIds(kind, directory, scan_subdirs) tests = [] for x in xrange(self.num_tests): tests.append("test%d" % x) return tests def GetTest(self, test_id): prereqs = [] for x in xrange(random.randrange(5)): test = "test%d" % random.randrange(self.num_tests) outcome = random.choice(Result.outcomes) prereqs.append((test, outcome)) return TestDescriptor(self, test_id, "throughput.ThroughputTest", { Test.PREREQUISITES_FIELD_ID : prereqs }) qmtest-2.4.1/COPYING0000664000076400007640000004311611107032237013423 0ustar stefanstefan GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991, 2002 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. qmtest-2.4.1/MANIFEST.in0000664000076400007640000000216111110732520014115 0ustar stefanstefan######################################################################## # # File: MANIFEST.in # Author: Stefan Seefeld # Date: 2003-08-28 # # Contents: # qmtest - Distutils distribution files # # Copyright (c) 2003-2007 by CodeSourcery, Inc. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## include ChangeLog COPYING LICENSE.OPL README NEWS qm/external/DocumentTemplate/LICENSE.txt include MANIFEST.in setup.py # These are the modules included in the 'qm' package. recursive-include qm *.py # Scripts include scripts/* # These are documentation sources (docbook) and compilation harness (xslt etc.) recursive-include doc * # These are data files used by various parts of QMTest. include qm/test/classes/classes.qmc recursive-include share * recursive-include templates * recursive-include benchmarks * recursive-include tests * recursive-include scripts * # These are extension modules for the build system. recursive-include qmdist * # Suppress svn bookkeeping files. global-exclude */.svn/* qmtest-2.4.1/setup.py0000664000076400007640000001002711122064030014066 0ustar stefanstefan######################################################################## # # File: setup.py # Author: Stefan Seefeld # Date: 2003-08-25 # # Contents: # Installation script for the qmtest package # # Copyright (c) 2003 by CodeSourcery. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from distutils.core import setup, Extension from qmdist.command.build import build from qmdist.command.build_py import build_py from qmdist.command.build_scripts import build_scripts from qmdist.command.build_doc import * from qmdist.command.install_lib import install_lib from qmdist.command.bdist_wininst import bdist_wininst from qmdist.command.check import check import sys, os, os.path, glob, shutil version='2.4.1' if sys.platform != "win32": # We need the sigmask extension on POSIX systems, but don't # want it on Win32. ext_modules = [Extension("qm.sigmask", ["qm/sigmask.c"])] scripts = ['scripts/qmtest'] else: ext_modules = [] shutil.copyfile('scripts/qmtest', 'scripts/qmtest.py') scripts = ['scripts/qmtest.py', 'scripts/qmtest-postinstall.py'] def include(d, e): """Generate a pair of (directory, file-list) for installation. 'd' -- A directory 'e' -- A glob pattern""" return (d, [f for f in glob.glob('%s/%s'%(d, e)) if os.path.isfile(f)]) setup(name="qmtest", version=version, author="CodeSourcery", author_email="info@codesourcery.com", maintainer="CodeSourcery", maintainer_email="qmtest@codesourcery.com", url="http://www.codesourcery.com/qmtest", description="QMTest is an automated software test execution tool.", cmdclass={'build': build, 'build_py': build_py, 'build_scripts': build_scripts, 'build_doc': build_doc, 'build_html_tutorial': build_html_tutorial, 'build_pdf_tutorial': build_pdf_tutorial, 'build_ref_manual': build_ref_manual, 'build_man_page': build_man_page, 'install_lib': install_lib, 'bdist_wininst' : bdist_wininst, 'check': check}, packages=('qm', 'qm/dist', 'qm/dist/command', 'qm/external', 'qm/external/DocumentTemplate', 'qm/test', 'qm/test/classes', 'qm/test/web'), ext_modules=ext_modules, scripts=scripts, data_files=[include('share/qmtest/messages', '*.txt'), include('share/qmtest/diagnostics', '*.txt'), # The documentation. ('share/doc/qmtest', ('ChangeLog', 'README', 'NEWS', 'COPYING', 'LICENSE.OPL')), include('share/man/man1', '*'), include('share/doc/qmtest/html/tutorial', '*'), include('share/doc/qmtest/print', 'tutorial.pdf'), include('share/doc/qmtest/examples/xml_tdb', '*'), include('share/doc/qmtest/examples/xml_tdb/QMTest', 'configuration'), include('share/doc/qmtest/examples/compilation_tdb', '*'), include('share/doc/qmtest/examples/compilation_tdb/subdir', '*'), include('share/doc/qmtest/examples/compilation_tdb/QMTest', 'configuration'), # The GUI. include('share/qmtest/dtml', '*.dtml'), include('share/qmtest/dtml/test', '*.dtml'), include('share/qmtest/dtml/report', '*.dtml'), include('share/qmtest/web', '*.js'), include('share/qmtest/web/images', '*.gif'), include('share/qmtest/web/stylesheets', '*.css'), include('share/qmtest/xml', '*'), include('share/qmtest/dtds', '*.dtd') ], ) qmtest-2.4.1/templates/0000775000076400007640000000000011122067201014355 5ustar stefanstefanqmtest-2.4.1/templates/py0000664000076400007640000000207011107032237014733 0ustar stefanstefan######################################################################## # # File: Fill me in! # Author: Fill me in! # Date: YYYY-MM-DD # # Contents: # Fill me in! # # Copyright (c) 2004 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## # Import modules here. ######################################################################## # Classes ######################################################################## # Place class definitions here. ######################################################################## # Functions ######################################################################## # Place function definitions here. ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/templates/docbook0000664000076400007640000000144211110103576015724 0ustar stefanstefan ]> Fill me in! Fill me in! qmtest-2.4.1/templates/dtml0000664000076400007640000000124411107032237015245 0ustar stefanstefan qmtest-2.4.1/templates/html0000664000076400007640000000133511107032237015252 0ustar stefanstefan Fill me in!

Text goes here.

qmtest-2.4.1/templates/xml0000664000076400007640000000032211107032237015101 0ustar stefanstefan qmtest-2.4.1/templates/Makefile0000664000076400007640000000052311107032237016021 0ustar stefanstefan######################################################### -*-Makefile-*- # # File: Makefile (template) # Author: Fill me in! # Date: YYYY-MM-DD # # Contents: # Fill me in! # # Copyright (C) 2004 CodeSourcery LLC # # For license terms see the file COPYING. # ######################################################################## qmtest-2.4.1/templates/docbook-chapter0000664000076400007640000000116111110110666017344 0ustar stefanstefan Fill me in! qmtest-2.4.1/scripts/0000775000076400007640000000000011122067201014046 5ustar stefanstefanqmtest-2.4.1/scripts/qmtest0000775000076400007640000001127311120047325015320 0ustar stefanstefan#! /usr/bin/env python ######################################################################## # # File: qmtest # Author: Alex Samuel # Date: 2001-03-15 # # Contents: # QMTest command line application. # # Copyright (c) 2001 - 2006 by CodeSourcery. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Check Python Version ######################################################################## # Before doing anything else, check that the version of Python in use # is sufficiently recent. All code in this section should be portable # even to old versions of Python. import sys def check_python_version(): """Check to see if the Python interpreter in use is acceptable. If the Python interpreter is not sufficiently recent, issue an error message and exit.""" required_python_version = (2, 2) # Get the version of Python in use. try: actual_version = sys.version_info except: # Older versions of Python do not have "sys.version_info". actual_version = (0, 0, 0, 0) old = 0 for i in range(len(required_python_version)): if required_python_version[i] > actual_version[i]: old = 1 if old: if len(required_python_version) == 2: version = "%d.%d" % required_python_version else: version = "%d.%d.%d" % required_python_version sys.stderr.write("qmtest: error: QMTest requires Python %s or later.\n" % version) sys.exit(1) check_python_version() ######################################################################## # Imports ######################################################################## import errno import gc import os import os.path import string import traceback import qm import qm.cmdline import qm.diagnostic import qm.platform import qm.structured_text import qm.test.cmdline if sys.platform != "win32": import qm.sigmask ######################################################################## # Functions ######################################################################## def print_error_message(message): """Output an error message. 'message' -- Structured text for the error message to emit. The messing is emitted to the standard error stream with an identifying prefix.""" prefix = "qmtest: error: " message = qm.structured_text.to_text(str(message), indent=len(prefix)) message = prefix + message[len(prefix):] sys.stderr.write(message) def main(): """Run QMTest. returns -- The exit code that should be provided to the operating system.""" # Save the initial signal mask, as early as possible. if sys.platform != "win32": qm.sigmask.save_mask() # Parse the command line. command = qm.test.cmdline.QMTest(sys.argv[1:], sys.argv[0]) # Execute the command. exit_code = command.Execute() return exit_code ######################################################################## # script ######################################################################## # Assume that something will go wrong. exit_code = 2 try: # Set the program name. qm.common.program_name = "QMTest" # Load messages. qm.diagnostic.load_messages("test") # Load RC options. qm.rc.Load("test") try: exit_code = main() except qm.cmdline.CommandError, msg: print_error_message(msg) sys.stderr.write( "Run 'qmtest --help' to get instructions about how to use QMTest.\n") except qm.common.QMException, msg: print_error_message(msg) except NotImplementedError: exc_info = sys.exc_info() method_name = traceback.extract_tb(exc_info[2])[-1][2] print_error_message(qm.message("not implemented", method_name = method_name)) sys.stderr.write(qm.common.format_traceback(exc_info)) except KeyboardInterrupt: sys.stderr.write("\nqmtest: Interrupted.\n") raise except qm.platform.SignalException, se: # SIGTERM indicates a request to shut down. Other signals # should be handled earlier. if se.GetSignalNumber() != signal.SIGTERM: raise finally: # Collect garbage so that any "__del__" methods with externally # visible side-effects are executed. del qm.test.cmdline._the_qmtest gc.collect() # End the program. sys.exit(exit_code) ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # End: qmtest-2.4.1/scripts/qmtest-postinstall.py0000664000076400007640000000255511107032214020315 0ustar stefanstefan# Post installation script for the Windows installer # This script is needed to adjust variables in qm/config.py # typically set during installation. from os.path import join import sys, re from distutils import sysconfig def reset_config_variables(config_file, **vars): """Reset specific variables in the given config file to new values. 'config_file' -- The config file to modify. 'vars' -- dict object containing variables to reset, with their new values. """ script = open(config_file, 'r').read() for v in vars: script, found = re.subn('%s=.*'%v,'%s=%s'%(v, repr(vars[v])), script) if not found: script += '%s=%s'%(v, repr(vars[v])) open(config_file, 'w').write(script) def install(): print 'Adjusting configuration parameters...' site_packages = join(sysconfig.get_config_var('BINLIBDEST'), 'site-packages') config_file = join(site_packages, 'qm', 'config.py') prefix = sysconfig.get_config_var('prefix') version = sys.version_info[:2] extension_path = join('share', 'qmtest', 'site-extensions-%d.%d'%version) reset_config_variables(config_file, prefix=prefix, extension_path=extension_path) print 'Done.' def remove(): pass if __name__ == '__main__': mode = sys.argv[1] if mode == '-install': install() elif mode == '-remove': remove() qmtest-2.4.1/scripts/qmtest~0000775000076400007640000001127311107032214015512 0ustar stefanstefan#! /usr/bin/env python ######################################################################## # # File: qmtest # Author: Alex Samuel # Date: 2001-03-15 # # Contents: # QMTest command line application. # # Copyright (c) 2001 - 2006 by CodeSourcery. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Check Python Version ######################################################################## # Before doing anything else, check that the version of Python in use # is sufficiently recent. All code in this section should be portable # even to old versions of Python. import sys def check_python_version(): """Check to see if the Python interpreter in use is acceptable. If the Python interpreter is not sufficiently recent, issue an error message and exit.""" required_python_version = (2, 2) # Get the version of Python in use. try: actual_version = sys.version_info except: # Older versions of Python do not have "sys.version_info". actual_version = (0, 0, 0, 0) old = 0 for i in range(len(required_python_version)): if required_python_version[i] > actual_version[i]: old = 1 if old: if len(required_python_version) == 2: version = "%d.%d" % required_python_version else: version = "%d.%d.%d" % required_python_version sys.stderr.write("qmtest: error: QMTest requires Python %s or later.\n" % version) sys.exit(1) check_python_version() ######################################################################## # Imports ######################################################################## import errno import gc import os import os.path import string import traceback import qm import qm.cmdline import qm.diagnostic import qm.platform import qm.structured_text import qm.test.cmdline if sys.platform != "win32": import qm.sigmask ######################################################################## # Functions ######################################################################## def print_error_message(message): """Output an error message. 'message' -- Structured text for the error message to emit. The messing is emitted to the standard error stream with an identifying prefix.""" prefix = "qmtest: error: " message = qm.structured_text.to_text(str(message), indent=len(prefix)) message = prefix + message[len(prefix):] sys.stderr.write(message) def main(): """Run QMTest. returns -- The exit code that should be provided to the operating system.""" # Save the initial signal mask, as early as possible. if sys.platform != "win32": qm.sigmask.save_mask() # Parse the command line. command = qm.test.cmdline.QMTest(sys.argv[1:], sys.argv[0]) # Execute the command. exit_code = command.Execute() return exit_code ######################################################################## # script ######################################################################## # Assume that something will go wrong. exit_code = 2 try: # Set the program name. qm.common.program_name = "QMTest" # Load messages. qm.diagnostic.load_messages("test") # Load RC options. qm.rc.Load("test") try: exit_code = main() except qm.cmdline.CommandError, msg: print_error_message(msg) sys.stderr.write( "Run 'qmtest --help' to get instructions about how to use QMTest.\n") except qm.common.QMException, msg: print_error_message(msg) except NotImplementedError: exc_info = sys.exc_info() method_name = traceback.extract_tb(exc_info[2])[-1][2] print_error_message(qm.message("not implemented", method_name = method_name)) sys.stderr.write(qm.common.format_traceback(exc_info)) except KeyboardInterrupt: sys.stderr.write("\nqmtest: Interrupted.\n") raise except qm.platform.SignalException, se: # SIGTERM indicates a request to shut down. Other signals # should be handled earlier. if se.GetSignalNumber() != signal.SIGTERM: raise finally: # Collect garbage so that any "__del__" methods with externally # visible side-effects are executed. del qm.test.cmdline._the_qmtest gc.collect() # End the program. sys.exit(exit_code) ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # End: qmtest-2.4.1/scripts/create-results-database.py0000664000076400007640000000477411107032214021137 0ustar stefanstefan#!/usr/bin/env python ######################################################################## # # File: create-results-database.py # Author: Nathaniel Smith # Date: 2003-07-02 # # Contents: # Script to set up a PostgreSQL results database. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import sys import pgdb ######################################################################## # Script ######################################################################## if len(sys.argv) != 2: print "Usage: %s " % (sys.argv[0],) sys.exit(1) dbname = sys.argv[1] cxn = pgdb.connect(database=dbname) cursor = cxn.cursor() cursor.execute(""" CREATE TABLE db_schema_version ( version INT ) """) cursor.execute(""" INSERT INTO db_schema_version (version) VALUES (1) """) cursor.execute(""" CREATE SEQUENCE run_id_seq """) cursor.execute(""" CREATE TABLE runs ( run_id INT PRIMARY KEY ) """) cursor.execute(""" CREATE TABLE run_annotations ( run_id INT NOT NULL, key TEXT NOT NULL, value TEXT NOT NULL, FOREIGN KEY (run_id) REFERENCES runs (run_id), PRIMARY KEY (run_id, key) ) """) cursor.execute(""" CREATE TABLE results ( run_id INT NOT NULL, result_id TEXT NOT NULL, kind TEXT NOT NULL, outcome TEXT NOT NULL, FOREIGN KEY (run_id) REFERENCES runs (run_id), PRIMARY KEY (run_id, result_id, kind) ) """) cursor.execute(""" CREATE INDEX results_outcome_idx ON results (run_id, outcome) """) cursor.execute(""" CREATE INDEX results_kind_idx ON results (run_id, kind) """) cursor.execute(""" CREATE TABLE result_annotations ( run_id INT NOT NULL, result_id TEXT NOT NULL, result_kind TEXT NOT NULL, key TEXT NOT NULL, value TEXT NOT NULL, FOREIGN KEY (run_id, result_id, result_kind) REFERENCES results (run_id, result_id, kind), PRIMARY KEY (run_id, result_id, result_kind, key) ) """) cxn.commit() ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/tests/0000775000076400007640000000000011122067201013521 5ustar stefanstefanqmtest-2.4.1/tests/regress/0000775000076400007640000000000011122067201015173 5ustar stefanstefanqmtest-2.4.1/tests/regress/env_context1/0000775000076400007640000000000011122067201017610 5ustar stefanstefanqmtest-2.4.1/tests/regress/env_context1/exectest_dot.qmt0000664000076400007640000000143511107032202023024 0ustar stefanstefan .*foo.bar0printenvQMV_foo__bar-1qmtest-2.4.1/tests/regress/env_context1/shellcommandtest_nodot.qmt0000664000076400007640000000133611107032202025103 0ustar stefanstefan .*echo ${QMV_foo}-1foo0qmtest-2.4.1/tests/regress/env_context1/shellscripttest_dot.qmt0000664000076400007640000000142111107032202024427 0ustar stefanstefan foo.barecho ${QMV_foo__bar}.*0-1qmtest-2.4.1/tests/regress/env_context1/shellcommandtest_dot.qmt0000664000076400007640000000134711107032202024550 0ustar stefanstefan .*echo ${QMV_foo__bar}-1foo.bar0qmtest-2.4.1/tests/regress/env_context1/shellscripttest_nodot.qmt0000664000076400007640000000141011107032202024762 0ustar stefanstefan fooecho ${QMV_foo}.*0-1qmtest-2.4.1/tests/regress/env_context1/QMTest/0000775000076400007640000000000011122067201020765 5ustar stefanstefanqmtest-2.4.1/tests/regress/env_context1/QMTest/configuration0000664000076400007640000000033411107032202023553 0ustar stefanstefan qmtest-2.4.1/tests/regress/env_context1/context0000664000076400007640000000003011107032202021204 0ustar stefanstefanfoo=foo foo.bar=foo.bar qmtest-2.4.1/tests/regress/env_context1/results.qmr0000664000076400007640000000105011107032202022022 0ustar stefanstefanK. N..(U annotationqUfooqUfooqt.N.[(U annotationqUfoo.barqUfoo.barqt.N.(U annotationqUqmtest.run.start_timeqU2003-08-11T17:53:10Zqt.(cqm.test.result Result qoq(UtestqU exectest_dotqUPASSq}q U qmtest.targetq Ulocalq stb.(hoq (hUexectest_nodotq h}qh h stb.(hoq(hUshellcommandtest_dotqh}qh h stb.(hoq(hUshellcommandtest_nodotqh}qh h stb.(hoq(hUshellscripttest_dotqh}qh h stb.(hoq(hUshellscripttest_nodotqh}qh h stb.N.(U annotationqUqmtest.run.end_timeqU2003-08-11T17:53:11Zqt.qmtest-2.4.1/tests/regress/env_context1/exectest_nodot.qmt0000664000076400007640000000142411107032202023357 0ustar stefanstefan .*foo0printenvQMV_foo-1qmtest-2.4.1/tests/regress/xml2/0000775000076400007640000000000011122067201016055 5ustar stefanstefanqmtest-2.4.1/tests/regress/xml2/asdfasdf.qmt0000775000076400007640000000076111107032177020371 0ustar stefanstefan command.ExecTest1.*a=btest qmtest-2.4.1/tests/regress/xml2/ids0000664000076400007640000000000211107032177016556 0ustar stefanstefans qmtest-2.4.1/tests/regress/xml2/s.qms0000664000076400007640000000016611107032177017053 0ustar stefanstefan asdfasdf fnord qmtest-2.4.1/tests/regress/xml2/fnord.qmt0000775000076400007640000000070211107032177017721 0ustar stefanstefan command.ExecTest0.*true qmtest-2.4.1/tests/regress/xml2/QMTest/0000775000076400007640000000000011122067201017232 5ustar stefanstefanqmtest-2.4.1/tests/regress/xml2/QMTest/configuration0000775000076400007640000000015511107032177022037 0ustar stefanstefan qm.test.xmldb.Databaseqmtest-2.4.1/tests/regress/xml2/results.qmr0000775000076400007640000000064311107032177020314 0ustar stefanstefan PASSlocal PASSlocal qmtest-2.4.1/tests/regress/resource_ordering/0000775000076400007640000000000011122067201020713 5ustar stefanstefanqmtest-2.4.1/tests/regress/resource_ordering/foo.qmt0000664000076400007640000000074211107032177022233 0ustar stefanstefan pass.*1hqmtest-2.4.1/tests/regress/resource_ordering/a.qma0000664000076400007640000000045211107032177021643 0ustar stefanstefan qmtest-2.4.1/tests/regress/resource_ordering/d.qma0000664000076400007640000000051311107032177021644 0ustar stefanstefan cbqmtest-2.4.1/tests/regress/resource_ordering/h.qma0000664000076400007640000000051311107032177021650 0ustar stefanstefan gfqmtest-2.4.1/tests/regress/resource_ordering/c.qma0000664000076400007640000000045211107032177021645 0ustar stefanstefan qmtest-2.4.1/tests/regress/resource_ordering/b.qma0000664000076400007640000000047511107032177021651 0ustar stefanstefan aqmtest-2.4.1/tests/regress/resource_ordering/f.qma0000664000076400007640000000047511107032177021655 0ustar stefanstefan eqmtest-2.4.1/tests/regress/resource_ordering/g.qma0000664000076400007640000000047511107032177021656 0ustar stefanstefan fqmtest-2.4.1/tests/regress/resource_ordering/QMTest/0000775000076400007640000000000011122067201022070 5ustar stefanstefanqmtest-2.4.1/tests/regress/resource_ordering/QMTest/dependency_checking_resource.py0000664000076400007640000000347011107032177030335 0ustar stefanstefan######################################################################## # # File: dependency_checking_resource.py # Author: Nathaniel Smith # Date: 2004-05-20 # # Contents: # A resource that checks that all its dependencies are set up before # it is, and aren't torn down until after it is. Of course, all the # resources it depends on have to be of the same type. # # Copyright (c) 2004 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.test.resource import Resource ######################################################################## # Classes ######################################################################## _extant_resources = {} class DependencyCheckingResource(Resource): def SetUp(self, context, result): # Make sure all resources we depend on have already been # set up. for r in self.resources: if not _extant_resources.has_key(r): result.Fail("Resource %s not set up yet" % r) # Mark ourself as set up. _extant_resources[self.GetId()] = 1 def CleanUp(self, result): # Make sure all resources we depend on are still set up. for r in self.resources: if not _extant_resources.has_key(r): result.Fail("Resource %s torn down already" % r) # Mark ourself as no longer set up. del _extant_resources[self.GetId()] ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/tests/regress/resource_ordering/QMTest/classes.qmc0000664000076400007640000000022511107032177024235 0ustar stefanstefan qmtest-2.4.1/tests/regress/resource_ordering/QMTest/configuration0000664000076400007640000000032411107032177024670 0ustar stefanstefan qmtest-2.4.1/tests/regress/resource_ordering/QMTest/dependency_checking_resource.pyc0000664000076400007640000000236711120047556030506 0ustar stefanstefan 4Ic@s0ddklZhZdefdYZdS(i(tResourcetDependencyCheckingResourcecBseZdZdZRS(cCsMx6|iD]+}ti|p|id|q q Wdt|isqmtest-2.4.1/tests/regress/resource_ordering/results.qmr0000664000076400007640000000222211107032177023142 0ustar stefanstefanK. N.Q(U annotationqUqmtest.run.start_timeqU2004-05-21T07:18:29Zqt.N.(U annotationqUqmtest.run.usernameqUnjsqt.N.(U annotationqUqmtest.run.useridqU501qt.N.(U annotationqUqmtest.run.versionqU2.2qt.N.Z(U annotationqUqmtest.run.unameqU>Linux WyrmWeyr 2.4.25 #5 SMP Sun Mar 14 04:02:01 PST 2004 i686qt.N.N(U annotationqUqmtest.run.command_lineqU-/home/njs/csl/qm/build/scripts-2.3/qmtest runqt.(cqm.test.result Result qoq(Uresource_setupqXcUPASSq}qU qmtest.targetq Ulocalq stb.(hoq (hXah}q h h stb.(hoq (hXbh}qh h stb.(hoq(hXdh}qh h stb.(hoq(hXeh}qh h stb.(hoq(hXfh}qh h stb.(hoq(hXgh}qh h stb.(hoq(hXhh}qh h stb.(hoq(UtestqUfooqh}q(h h Uqmtest.start_timeqU2004-05-21T07:18:29ZqUqmtest.end_timeqU2004-05-21T07:18:29Zq utb.(hoq!(Uresource_cleanupq"Xhh}q#h h stb.(hoq$(h"Xgh}q%h h stb.(hoq&(h"Xfh}q'h h stb.(hoq((h"Xeh}q)h h stb.(hoq*(h"Xdh}q+h h stb.(hoq,(h"Xbh}q-h h stb.(hoq.(h"Xah}q/h h stb.(hoq0(h"Xch}q1h h stb.N.(U annotationqUqmtest.run.end_timeqU2004-05-21T07:18:29Zqt.qmtest-2.4.1/tests/regress/resource_ordering/e.qma0000664000076400007640000000047511107032177021654 0ustar stefanstefan dqmtest-2.4.1/tests/regress/bad_target2/0000775000076400007640000000000011122067201017351 5ustar stefanstefanqmtest-2.4.1/tests/regress/bad_target2/bad_target.qmt0000664000076400007640000000073111107032202022165 0ustar stefanstefan passbad1 qmtest-2.4.1/tests/regress/bad_target2/a.qmt0000664000076400007640000000103411107032202020306 0ustar stefanstefan bad_targetPASSpass.*1 qmtest-2.4.1/tests/regress/bad_target2/QMTest/0000775000076400007640000000000011122067201020526 5ustar stefanstefanqmtest-2.4.1/tests/regress/bad_target2/QMTest/configuration0000664000076400007640000000033411107032202023314 0ustar stefanstefan qmtest-2.4.1/tests/regress/bad_target2/results.qmr0000664000076400007640000000100011107032202021556 0ustar stefanstefanK. N.(U annotationqUqmtest.run.start_timeqU2003-07-31T21:33:55Zqt.(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeq UUNTESTEDq U_Result__annotationsq }q U qmtest.causeq XNo target matching $^.qsU _Result__idqX bad_targetqub.(hoq}q(hhh h h }q(h U-A prerequisite produced an incorrect outcome.qUqmtest.expected_outcomeqXPASSqUqmtest.prequisiteqhUqmtest.outcomeqh uhUaub.N.(U annotationqUqmtest.run.end_timeqU2003-07-31T21:33:55Zqt.qmtest-2.4.1/tests/regress/nocycle2/0000775000076400007640000000000011122067201016711 5ustar stefanstefanqmtest-2.4.1/tests/regress/nocycle2/c.qmt0000664000076400007640000000073011107032202017652 0ustar stefanstefan pass.*1 qmtest-2.4.1/tests/regress/nocycle2/a.qmt0000664000076400007640000000111111107032202017642 0ustar stefanstefan bPASScPASSpass.*1 qmtest-2.4.1/tests/regress/nocycle2/b.qmt0000664000076400007640000000102311107032202017645 0ustar stefanstefan cPASSpass.*1 qmtest-2.4.1/tests/regress/nocycle2/QMTest/0000775000076400007640000000000011122067201020066 5ustar stefanstefanqmtest-2.4.1/tests/regress/nocycle2/QMTest/configuration0000664000076400007640000000033411107032202022654 0ustar stefanstefan qmtest-2.4.1/tests/regress/nocycle2/results.qmr0000664000076400007640000000060411107032202021127 0ustar stefanstefanK. N.@(U annotationqUqmtest.run.start_timeqU2003-07-31T21:34:48Zqt.(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeq UPASSq U_Result__annotationsq }q U qmtest.targetq UlocalqsU _Result__idqXcub.(hoq}q(hhh h h }qh hshXbub.(hoq}q(hhh h h }qh hshUaub.N.(U annotationqUqmtest.run.end_timeqU2003-07-31T21:34:48Zqt.qmtest-2.4.1/tests/regress/attachment1/0000775000076400007640000000000011122067201017404 5ustar stefanstefanqmtest-2.4.1/tests/regress/attachment1/attachment10000664000076400007640000000005611107032200021533 0ustar stefanstefanThe quick brown fox jumped over the lazy dog. qmtest-2.4.1/tests/regress/attachment1/test1.qmt0000664000076400007640000000071311107032200021162 0ustar stefanstefan .*attachment1application/octet-streamattachment1attachment1 qmtest-2.4.1/tests/regress/attachment1/QMTest/0000775000076400007640000000000011122067201020561 5ustar stefanstefanqmtest-2.4.1/tests/regress/attachment1/QMTest/attachment_test.py0000664000076400007640000000231711107032200024317 0ustar stefanstefan######################################################################## # # File: attachment_test.py # Author: Mark Mitchell # Date: 2003-07-21 # # Contents: # Test classes for tests written in Python. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm.fields from qm.test.test import Test ######################################################################## # Classes ######################################################################## class AttachmentTest(Test): """An 'AttachmentTest' has a single attachment. This test class is used to validate QMTest's attachment processing.""" arguments = [ qm.fields.AttachmentField( name="attachment" ) ] def Run(self, context, result): if (self.attachment.GetData() != "The quick brown fox jumped over the lazy dog.\n"): result.Fail("Incorrect attachment contents.") qmtest-2.4.1/tests/regress/attachment1/QMTest/classes.qmc0000664000076400007640000000016311107032200022712 0ustar stefanstefan attachment_test.AttachmentTestqmtest-2.4.1/tests/regress/attachment1/QMTest/configuration0000664000076400007640000000012411107032200023342 0ustar stefanstefan qmtest-2.4.1/tests/regress/attachment1/QMTest/attachment_test.pyc0000664000076400007640000000207011120047551024470 0ustar stefanstefan 4Ic@s6ddkZddklZdefdYZdS(iN(tTesttAttachmentTestcBs/eZdZeiiddgZdZRS(suAn 'AttachmentTest' has a single attachment. This test class is used to validate QMTest's attachment processing.tnamet attachmentcCs+|iidjo|idndS(Ns.The quick brown fox jumped over the lazy dog. sIncorrect attachment contents.(RtGetDatatFail(tselftcontexttresult((sL/home/stefan/work/qmtest/tests/regress/attachment1/QMTest/attachment_test.pytRun's  (t__name__t __module__t__doc__tqmtfieldstAttachmentFieldt argumentsR (((sL/home/stefan/work/qmtest/tests/regress/attachment1/QMTest/attachment_test.pyRs  (t qm.fieldsR t qm.test.testRR(((sL/home/stefan/work/qmtest/tests/regress/attachment1/QMTest/attachment_test.pyts qmtest-2.4.1/tests/regress/attachment1/results.qmr0000664000076400007640000000022111107032200021613 0ustar stefanstefanK.(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeqUPASSqU_Result__annotationsq}U _Result__idq Utest1q ub.qmtest-2.4.1/tests/regress/xml1/0000775000076400007640000000000011122067201016054 5ustar stefanstefanqmtest-2.4.1/tests/regress/xml1/asdfasdf.qmt0000664000076400007640000000076111107032177020365 0ustar stefanstefan command.ExecTest1.*a=btest qmtest-2.4.1/tests/regress/xml1/fnord.qmt0000664000076400007640000000070211107032177017715 0ustar stefanstefan command.ExecTest0.*true qmtest-2.4.1/tests/regress/xml1/QMTest/0000775000076400007640000000000011122067201017231 5ustar stefanstefanqmtest-2.4.1/tests/regress/xml1/QMTest/configuration0000664000076400007640000000015511107032177022033 0ustar stefanstefan qm.test.xmldb.Databaseqmtest-2.4.1/tests/regress/xml1/results.qmr0000664000076400007640000000064311107032177020310 0ustar stefanstefan PASSlocal PASSlocal qmtest-2.4.1/tests/regress/tuple1/0000775000076400007640000000000011122067201016405 5ustar stefanstefanqmtest-2.4.1/tests/regress/tuple1/tuple1.qmt0000664000076400007640000000046111107032200020335 0ustar stefanstefan .*3 qmtest-2.4.1/tests/regress/tuple1/QMTest/0000775000076400007640000000000011122067201017562 5ustar stefanstefanqmtest-2.4.1/tests/regress/tuple1/QMTest/tuple_test.pyc0000664000076400007640000000203711120047556022502 0ustar stefanstefan 4Ic@s6ddkZddklZdefdYZdS(iN(tTestt TupleTestcBsAeZdZeiideiiddfgZdZRS(skA 'TupleTest' has a single tuple field. This test class is used to validate QMTest's tuple processing.ttupletnametintegercCs;|idgjo$|idht|id6ndS(NisIncorrect tuple contents.sTupleTest.value(RtFailtstr(tselftcontexttresult((sB/home/stefan/work/qmtest/tests/regress/tuple1/QMTest/tuple_test.pytRun's ( t__name__t __module__t__doc__tqmtfieldst TupleFieldt IntegerFieldt argumentsR (((sB/home/stefan/work/qmtest/tests/regress/tuple1/QMTest/tuple_test.pyRs  (t qm.fieldsRt qm.test.testRR(((sB/home/stefan/work/qmtest/tests/regress/tuple1/QMTest/tuple_test.pyts qmtest-2.4.1/tests/regress/tuple1/QMTest/classes.qmc0000664000076400007640000000015111107032200021710 0ustar stefanstefan tuple_test.TupleTestqmtest-2.4.1/tests/regress/tuple1/QMTest/configuration0000664000076400007640000000012411107032200022343 0ustar stefanstefan qmtest-2.4.1/tests/regress/tuple1/QMTest/tuple_test.py0000664000076400007640000000231211107032200022314 0ustar stefanstefan######################################################################## # # File: tuple_test.py # Author: Mark Mitchell # Date: 2003-07-21 # # Contents: # Test classes for tests written in Python. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm.fields from qm.test.test import Test ######################################################################## # Classes ######################################################################## class TupleTest(Test): """A 'TupleTest' has a single tuple field. This test class is used to validate QMTest's tuple processing.""" arguments = [ qm.fields.TupleField( "tuple", (qm.fields.IntegerField(name = "integer"),)) ] def Run(self, context, result): if self.tuple != [3,]: result.Fail("Incorrect tuple contents.", { "TupleTest.value" : str(self.tuple) }) qmtest-2.4.1/tests/regress/tuple1/results.qmr0000664000076400007640000000047511107032200020627 0ustar stefanstefanK. N.(U annotationqUqmtest.run.start_timeqU2003-07-22T17:04:04Zqt.(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeq UPASSq U_Result__annotationsq }q U qmtest.targetq UlocalqsU _Result__idqUtuple1qub.N.(U annotationqUqmtest.run.end_timeqU2003-07-22T17:04:04Zqt.qmtest-2.4.1/tests/regress/exception_test/0000775000076400007640000000000011122067201020230 5ustar stefanstefanqmtest-2.4.1/tests/regress/exception_test/arg1.qmt0000664000076400007640000000122211107032200021574 0ustar stefanstefan MyExc 'this is the arg' class MyExc(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) raise MyExc('this is the arg') .* qmtest-2.4.1/tests/regress/exception_test/QMTest/0000775000076400007640000000000011122067201021405 5ustar stefanstefanqmtest-2.4.1/tests/regress/exception_test/QMTest/configuration0000664000076400007640000000012411107032200024166 0ustar stefanstefan qmtest-2.4.1/tests/regress/exception_test/results.qmr0000664000076400007640000000056311107032200022450 0ustar stefanstefanK. N./(U annotationqUqmtest.run.start_timeqU2004-01-12T21:52:45Zqt.(cqm.test.result Result qoq(UtestqUarg1qUFAILq}q (U qmtest.causeq UIException object does not provide access to arguments provided to 'raise'q U qmtest.targetq Ulocalq UExceptionTest.typeqU__builtin__.MyExcutb.N.(U annotationqUqmtest.run.end_timeqU2004-01-12T21:52:45Zqt.qmtest-2.4.1/tests/regress/gilles1/0000775000076400007640000000000011122067201016533 5ustar stefanstefanqmtest-2.4.1/tests/regress/gilles1/c.qmt0000664000076400007640000000042111107032200017467 0ustar stefanstefan python.ExecTest1.*passb qmtest-2.4.1/tests/regress/gilles1/a.qmt0000664000076400007640000000034411107032200017471 0ustar stefanstefan python.ExecTest0.*pass qmtest-2.4.1/tests/regress/gilles1/b.qmt0000664000076400007640000000042011107032200017465 0ustar stefanstefan python.ExecTest1.*passaqmtest-2.4.1/tests/regress/gilles1/QMTest/0000775000076400007640000000000011122067201017710 5ustar stefanstefanqmtest-2.4.1/tests/regress/gilles1/QMTest/configuration0000664000076400007640000000015511107032200022475 0ustar stefanstefan qm.test.xmldb.Databaseqmtest-2.4.1/tests/regress/gilles1/results.qmr0000664000076400007640000000204711107032200020752 0ustar stefanstefan FAIL00Expression evaluates to false.local UNTESTEDA prerequisite produced an incorrect outcome.PASSFAILa UNTESTEDA prerequisite produced an incorrect outcome.PASSUNTESTEDb qmtest-2.4.1/tests/regress/cycle2/0000775000076400007640000000000011122067201016354 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle2/c.qmt0000664000076400007640000000044111107032177017327 0ustar stefanstefan python.ExecTest 1 .* pass b qmtest-2.4.1/tests/regress/cycle2/a.qmt0000664000076400007640000000036111107032177017326 0ustar stefanstefan python.ExecTest 1 .* pass qmtest-2.4.1/tests/regress/cycle2/b.qmt0000664000076400007640000000052111107032177017325 0ustar stefanstefan python.ExecTest 1 .* pass a c qmtest-2.4.1/tests/regress/cycle2/QMTest/0000775000076400007640000000000011122067201017531 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle2/QMTest/configuration0000664000076400007640000000015511107032177022333 0ustar stefanstefan qm.test.xmldb.Databaseqmtest-2.4.1/tests/regress/cycle2/results.qmr0000664000076400007640000000141411107032177020605 0ustar stefanstefan PASSlocal UNTESTEDThis test depends on itself, either directly or by way of other tests. UNTESTEDA prerequisite produced an incorrect outcome.PASSUNTESTEDb qmtest-2.4.1/tests/regress/cycle5/0000775000076400007640000000000011122067201016357 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle5/a.qmt0000664000076400007640000000044111107032200017313 0ustar stefanstefan python.ExecTest 1 .* pass b qmtest-2.4.1/tests/regress/cycle5/b.qmt0000664000076400007640000000044511107032200017320 0ustar stefanstefan python.ExecTest 1 .* pass a qmtest-2.4.1/tests/regress/cycle5/QMTest/0000775000076400007640000000000011122067201017534 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle5/QMTest/configuration0000664000076400007640000000015511107032200022321 0ustar stefanstefan qm.test.xmldb.Databaseqmtest-2.4.1/tests/regress/cycle5/results.qmr0000664000076400007640000000073411107032200020577 0ustar stefanstefan UNTESTEDThis test depends on itself, either directly or by way of other tests. PASSlocal qmtest-2.4.1/tests/regress/noresource/0000775000076400007640000000000011122067201017357 5ustar stefanstefanqmtest-2.4.1/tests/regress/noresource/test.qmt0000664000076400007640000000046011107032200021053 0ustar stefanstefan python.ExecTesttest1.*passresourceqmtest-2.4.1/tests/regress/noresource/test2.qmt0000664000076400007640000000046211107032200021137 0ustar stefanstefan python.ExecTesttest21.*passresource qmtest-2.4.1/tests/regress/noresource/QMTest/0000775000076400007640000000000011122067201020534 5ustar stefanstefanqmtest-2.4.1/tests/regress/noresource/QMTest/configuration0000664000076400007640000000015711107032200023323 0ustar stefanstefan xml_database.XMLDatabaseqmtest-2.4.1/tests/regress/noresource/results.qmr0000664000076400007640000000256011107032200021576 0ustar stefanstefan ERRORsetupResource does not exist.qm.test.database.NoSuchResourceError: There is no resource with the resource ID "resource".local File "/home/zack/src/qm/qm/qm/test/target.py", line 310, in _SetUpResource resource = self.GetDatabase().GetResource(resource_name) File "/home/zack/src/qm/qm/qm/test/file_database.py", line 237, in GetResource raise NoSuchResourceError, resource_id UNTESTEDSetup of a required resource failed.resourcelocal UNTESTEDSetup of a required resource failed.resourcelocal qmtest-2.4.1/tests/regress/bad_prereq/0000775000076400007640000000000011122067201017277 5ustar stefanstefanqmtest-2.4.1/tests/regress/bad_prereq/a.qmt0000664000076400007640000000066011107032200020236 0ustar stefanstefan True bad_prereqPASS qmtest-2.4.1/tests/regress/bad_prereq/QMTest/0000775000076400007640000000000011122067201020454 5ustar stefanstefanqmtest-2.4.1/tests/regress/bad_prereq/QMTest/configuration0000664000076400007640000000032411107032200023237 0ustar stefanstefan qmtest-2.4.1/tests/regress/bad_prereq/results.qmr0000664000076400007640000000126111107032200021513 0ustar stefanstefanK. N.Q(U annotationqUqmtest.run.start_timeqU2005-07-20T00:30:49Zqt.N.(U annotationqUqmtest.run.usernameqUmitchellqt.N.(U annotationqUqmtest.run.useridqU515qt.N.(U annotationqUqmtest.run.versionqU2.3qt.N.}(U annotationqUqmtest.run.unameqU\Linux sethra.codesourcery.com 2.4.21-32.0.1.ELsmp #1 SMP Tue May 17 17:46:36 EDT 2005 x86_64qt.N.m(U annotationqUqmtest.run.command_lineqU(/home/mitchell/src/qm/qm/test/qmtest runqt.(cqm.test.result Result qoq(UtestqUaUUNTESTEDq}qU qmtest.causeq X?The non-existant test "bad_prereq" is listed as a prerequisite.q stb.N.(U annotationqUqmtest.run.end_timeqU2005-07-20T00:30:49Zqt.qmtest-2.4.1/tests/regress/cycle4/0000775000076400007640000000000011122067201016356 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle4/c.qmt0000664000076400007640000000044111107032200017314 0ustar stefanstefan python.ExecTest 1 .* pass d qmtest-2.4.1/tests/regress/cycle4/e.qmt0000664000076400007640000000044111107032200017316 0ustar stefanstefan python.ExecTest 1 .* pass f qmtest-2.4.1/tests/regress/cycle4/f.qmt0000664000076400007640000000044111107032200017317 0ustar stefanstefan python.ExecTest 1 .* pass e qmtest-2.4.1/tests/regress/cycle4/a.qmt0000664000076400007640000000036111107032200017313 0ustar stefanstefan python.ExecTest 1 .* pass qmtest-2.4.1/tests/regress/cycle4/b.qmt0000664000076400007640000000044111107032200017313 0ustar stefanstefan python.ExecTest 1 .* pass c qmtest-2.4.1/tests/regress/cycle4/d.qmt0000664000076400007640000000044111107032200017315 0ustar stefanstefan python.ExecTest 1 .* pass b qmtest-2.4.1/tests/regress/cycle4/QMTest/0000775000076400007640000000000011122067201017533 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle4/QMTest/configuration0000664000076400007640000000015511107032200022320 0ustar stefanstefan qm.test.xmldb.Databaseqmtest-2.4.1/tests/regress/cycle4/results.qmr0000664000076400007640000000303311107032200020571 0ustar stefanstefan PASSlocal UNTESTEDThis test depends on itself, either directly or by way of other tests. UNTESTEDA prerequisite produced an incorrect outcome.PASSUNTESTEDb UNTESTEDA prerequisite produced an incorrect outcome.PASSUNTESTEDd UNTESTEDThis test depends on itself, either directly or by way of other tests. UNTESTEDA prerequisite produced an incorrect outcome.PASSUNTESTEDe qmtest-2.4.1/tests/regress/nocycle1/0000775000076400007640000000000011122067201016710 5ustar stefanstefanqmtest-2.4.1/tests/regress/nocycle1/c.qmt0000664000076400007640000000102311107032201017644 0ustar stefanstefan dPASSpass.*1 qmtest-2.4.1/tests/regress/nocycle1/e.qmt0000664000076400007640000000075511107032201017661 0ustar stefanstefan import time time.sleep(1).*1 qmtest-2.4.1/tests/regress/nocycle1/a.qmt0000664000076400007640000000111111107032201017640 0ustar stefanstefan bPASScPASSpass.*1 qmtest-2.4.1/tests/regress/nocycle1/b.qmt0000664000076400007640000000102311107032201017643 0ustar stefanstefan dPASSpass.*1 qmtest-2.4.1/tests/regress/nocycle1/d.qmt0000664000076400007640000000102311107032201017645 0ustar stefanstefan ePASSpass.*1 qmtest-2.4.1/tests/regress/nocycle1/QMTest/0000775000076400007640000000000011122067201020065 5ustar stefanstefanqmtest-2.4.1/tests/regress/nocycle1/QMTest/configuration0000664000076400007640000000033411107032201022652 0ustar stefanstefan qmtest-2.4.1/tests/regress/nocycle1/results.qmr0000664000076400007640000000072211107032201021126 0ustar stefanstefanK. N.(U annotationqUqmtest.run.start_timeqU2003-07-31T21:34:37Zqt.(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeq UPASSq U_Result__annotationsq }q U qmtest.targetq UlocalqsU _Result__idqXeub.(hoq}q(hhh h h }qh hshXdub.(hoq}q(hhh h h }qh hshXbub.(hoq}q(hhh h h }qh hshXcub.(hoq}q(hhh h h }qh hshUaub.N.(U annotationqUqmtest.run.end_timeqU2003-07-31T21:34:38Zqt.qmtest-2.4.1/tests/regress/QMTest/0000775000076400007640000000000011122067201016350 5ustar stefanstefanqmtest-2.4.1/tests/regress/QMTest/regression_database.py0000664000076400007640000000360111107032202022722 0ustar stefanstefan######################################################################## # # File: regression_database.py # Author: Mark Mitchell # Date: 03/20/2003 # # Contents: # QMTest regression database class. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## import dircache import os.path from qm.test.database import * ######################################################################## # Classes ######################################################################## class RegressionDatabase(Database): """Database storing regression tests for QMTest. This database is read-only, i.e. the methods to update it through the GUI are not implemented. It is expected that users will update it by creating new test databases manually. Currently, there are no subdirectories and no resources in this database.""" def __init__(self, path, arguments): arguments["modifiable"] = "false" Database.__init__(self, path, arguments) def GetTest(self, test_id): path = os.path.join(self.GetPath(), test_id) if not is_database(path): raise NoSuchTestError return TestDescriptor(self, test_id, 'selftest.RegTest', { 'path' : path }) def GetIds(self, kind, directory = "", scan_subdirs = 1): assert directory == "" ids = [] # There are no suites or resources in this database. if kind == Database.TEST: p = self.GetPath() for entry in dircache.listdir(p): if is_database(os.path.join(p, entry)): ids.append(entry) return ids qmtest-2.4.1/tests/regress/QMTest/classes.qmc0000664000076400007640000000025211107032202020502 0ustar stefanstefan regression_database.RegressionDatabaseselftest.RegTestqmtest-2.4.1/tests/regress/QMTest/selftest.py0000664000076400007640000001100411107032202020543 0ustar stefanstefan######################################################################## # # File: selftest.py # Author: Zack Weinberg # Date: 2002-08-05 # # Contents: # Test database specific to QMTest self-test suite. # # Copyright (c) 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import os import os.path import re import qm.executable from qm.test.test import * from qm.test.result import * ######################################################################## # classes ######################################################################## class RegTest(Test): """A 'RegTest' performs a regression test on QMTest itself. Each regression test is stored as a subdirectory of the 'regress' directory. Each such subdirectory is a complete test database in itself, such that running "qmtest -D . run -O results.qmr" in that directory should succeed, reporting all tests completed as expected. The test is judged to have succeeded if so. The context key "qmtest_path" should contain the path to the qmtest executable. If the context key "qmtest_target" is defined, the test database will be run using that target. If the test database contains a file "context", then the test database will be run with it as a context file.""" arguments = [ qm.fields.TextField( name = "path", title = "Path to test", verbatim = "true", multiline = "false", description = """The pathname of the test. This is a path to a directory in the file system containing a complete, self-contained test database. All the tests in this database will be executed to perform the regression test.""" ) ] # This pattern is matched against the output of a QMTest subprocess # to determine if there were any unexpected outcomes. good_outcome_pat = re.compile( r"^-+\s+TESTS\s+WITH\s+UNEXPECTED\s+OUTCOMES\s+-+\s+None", re.MULTILINE) def Run(self, context, result): path = self.path results = os.path.join(path, "results.qmr") output = os.path.join(path, "output.qmr") context_file = os.path.join(path, "context") ids_file = os.path.join(path, "ids") # Sanity check the target location. assert os.path.isdir(os.path.join(path, "QMTest")) assert os.path.isfile(results) # The QMTest binary to test is specified as a context variable. qmtest = context['qmtest_path'] # Set the basic argument vector. argv = (qmtest, "-D", path, "run", "-O", results, "-o", output) # If the context also specifies a target, add that. if context.has_key("qmtest_target"): argv += ("-T", context["qmtest_target"]) # And if there is a context file, use it. if os.path.exists(context_file): argv += ("-C", context_file) # And if there is a file containing ids to run, use it. if os.path.exists(ids_file): argv += tuple(open(ids_file).readline().split()) e = qm.executable.RedirectedExecutable() status = e.Run(argv) stdout = e.stdout stderr = e.stderr result.Annotate({ "selftest.RegTest.cmdline" : result.Quote(' '.join(argv)), "selftest.RegTest.exitcode" : ("%d" % status), "selftest.RegTest.stdout" : result.Quote(stdout), "selftest.RegTest.stderr" : result.Quote(stderr), }) if stderr != '': # Printing anything to stderr is a failure. result.Fail("Child process reported errors") elif status: # Unsuccessful termination is a failure. This is checked # second because output on stderr should come along with # an unsuccessful exit, and we want to pick the more specific # failure cause. result.Fail("Child process exited unsuccessfully") elif self.good_outcome_pat.search(stdout) is None: # If there were unexpected outcomes, it's a failure. result.Fail("Unexpected outcomes reported") else: # Success. Delete the uninteresting output file. os.remove(output) qmtest-2.4.1/tests/regress/QMTest/configuration0000664000076400007640000000014211107032202021133 0ustar stefanstefan qmtest-2.4.1/tests/regress/QMTest/regression_database.pyc0000664000076400007640000000365611120047551023107 0ustar stefanstefan 4Ic@s<ddkZddkZddkTdefdYZdS(iN(t*tRegressionDatabasecBs/eZdZdZdZdddZRS(s?Database storing regression tests for QMTest. This database is read-only, i.e. the methods to update it through the GUI are not implemented. It is expected that users will update it by creating new test databases manually. Currently, there are no subdirectories and no resources in this database.cCs!d|ds   qmtest-2.4.1/tests/regress/QMTest/selftest.pyc0000664000076400007640000000652511120047551020732 0ustar stefanstefan 4Ic @s^ddkZddkZddkZddkZddkTddkTdefdYZdS(iN(t*tRegTestc Bs\eZdZeiiddddddddd d gZeid ei Z d Z RS( sA 'RegTest' performs a regression test on QMTest itself. Each regression test is stored as a subdirectory of the 'regress' directory. Each such subdirectory is a complete test database in itself, such that running "qmtest -D . run -O results.qmr" in that directory should succeed, reporting all tests completed as expected. The test is judged to have succeeded if so. The context key "qmtest_path" should contain the path to the qmtest executable. If the context key "qmtest_target" is defined, the test database will be run using that target. If the test database contains a file "context", then the test database will be run with it as a context file.tnametpathttitles Path to testtverbatimttruet multilinetfalset descriptionsThe pathname of the test. This is a path to a directory in the file system containing a complete, self-contained test database. All the tests in this database will be executed to perform the regression test.s6^-+\s+TESTS\s+WITH\s+UNEXPECTED\s+OUTCOMES\s+-+\s+NonecCsB|i}tii|d}tii|d}tii|d}tii|d}tiitii|dpttii|pt|d}|d|dd |d |f} |id o| d |d f7} ntii|o| d |f7} ntii|o&| tt |i i 7} nt i i} | i| } | i} | i} |ih|idi| d6d| d6|i| d6|i| d6| djo|idnP| o|idn8|ii| djo|idnti|dS(Ns results.qmrs output.qmrtcontexttidstQMTestt qmtest_paths-Dtruns-Os-ot qmtest_targets-Ts-Ct sselftest.RegTest.cmdlines%dsselftest.RegTest.exitcodesselftest.RegTest.stdoutsselftest.RegTest.stderrtsChild process reported errorss#Child process exited unsuccessfullysUnexpected outcomes reported(RtostjointisdirtAssertionErrortisfilethas_keytexiststtupletopentreadlinetsplittqmt executabletRedirectedExecutabletRuntstdouttstderrtAnnotatetQuotetFailtgood_outcome_pattsearchtNonetremove(tselfR tresultRtresultstoutputt context_filetids_filetqmtesttargvtetstatusR!R"((s9/home/stefan/work/qmtest/tests/regress/QMTest/selftest.pyR Bs> ) &     ( t__name__t __module__t__doc__Rtfieldst TextFieldt argumentstretcompilet MULTILINER&R (((s9/home/stefan/work/qmtest/tests/regress/QMTest/selftest.pyRs    ( Rtos.pathR:t qm.executableRt qm.test.testtqm.test.resulttTestR(((s9/home/stefan/work/qmtest/tests/regress/QMTest/selftest.pyts      qmtest-2.4.1/tests/regress/bad_target1/0000775000076400007640000000000011122067201017350 5ustar stefanstefanqmtest-2.4.1/tests/regress/bad_target1/bad_target.qmt0000664000076400007640000000073111107032202022164 0ustar stefanstefan passbad1 qmtest-2.4.1/tests/regress/bad_target1/a.qmt0000664000076400007640000000072711107032202020315 0ustar stefanstefan pass.*1qmtest-2.4.1/tests/regress/bad_target1/QMTest/0000775000076400007640000000000011122067201020525 5ustar stefanstefanqmtest-2.4.1/tests/regress/bad_target1/QMTest/configuration0000664000076400007640000000033411107032202023313 0ustar stefanstefan qmtest-2.4.1/tests/regress/bad_target1/results.qmr0000664000076400007640000000063011107032202021565 0ustar stefanstefanK. N.T(U annotationqUqmtest.run.start_timeqU2003-07-31T21:33:51Zqt.(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeq UPASSq U_Result__annotationsq }q U qmtest.targetq UlocalqsU _Result__idqUaub.(hoq}q(hhh UUNTESTEDqh }qU qmtest.causeqXNo target matching $^.qshU bad_targetqub.N.(U annotationqUqmtest.run.end_timeqU2003-07-31T21:33:51Zqt.qmtest-2.4.1/tests/regress/cycle1/0000775000076400007640000000000011122067201016353 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle1/a.qmt0000664000076400007640000000044111107032176017323 0ustar stefanstefan python.ExecTest 1 .* pass b qmtest-2.4.1/tests/regress/cycle1/b.qmt0000664000076400007640000000044111107032176017324 0ustar stefanstefan python.ExecTest 1 .* pass a qmtest-2.4.1/tests/regress/cycle1/QMTest/0000775000076400007640000000000011122067201017530 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle1/QMTest/configuration0000664000076400007640000000015511107032176022331 0ustar stefanstefan qm.test.xmldb.Databaseqmtest-2.4.1/tests/regress/cycle1/results.qmr0000664000076400007640000000124111107032176020601 0ustar stefanstefan UNTESTEDThis test depends on itself, either directly or by way of other tests. UNTESTEDA prerequisite produced an incorrect outcome.PASSUNTESTEDa qmtest-2.4.1/tests/regress/cycle3/0000775000076400007640000000000011122067201016355 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle3/c.qmt0000664000076400007640000000044111107032177017330 0ustar stefanstefan python.ExecTest 1 .* pass a qmtest-2.4.1/tests/regress/cycle3/a.qmt0000664000076400007640000000044111107032177017326 0ustar stefanstefan python.ExecTest 1 .* pass b qmtest-2.4.1/tests/regress/cycle3/b.qmt0000664000076400007640000000044111107032177017327 0ustar stefanstefan python.ExecTest 1 .* pass c qmtest-2.4.1/tests/regress/cycle3/QMTest/0000775000076400007640000000000011122067201017532 5ustar stefanstefanqmtest-2.4.1/tests/regress/cycle3/QMTest/configuration0000664000076400007640000000015511107032177022334 0ustar stefanstefan qm.test.xmldb.Databaseqmtest-2.4.1/tests/regress/cycle3/results.qmr0000664000076400007640000000172111107032177020607 0ustar stefanstefan UNTESTEDThis test depends on itself, either directly or by way of other tests. UNTESTEDA prerequisite produced an incorrect outcome.PASSUNTESTEDa UNTESTEDA prerequisite produced an incorrect outcome.PASSUNTESTEDc qmtest-2.4.1/tests/xmldb/0000775000076400007640000000000011122067201014627 5ustar stefanstefanqmtest-2.4.1/tests/xmldb/signals_unblocked.qmt0000664000076400007640000000252411107032176021051 0ustar stefanstefan .*0if ! which cc >/dev/null; then echo "No cc, skipping test" exit 1 fi cd $QMV_temp_dir_path cat >check_sigmask.c <<EOF #include <signal.h> int main(int argc, char** argv) { sigset_t s; sigprocmask(SIG_BLOCK, 0, &s); return (sigismember(&s, SIGTERM) || sigismember(&s, SIGXCPU)); } EOF cc check_sigmask.c -o check_sigmask if ! ./check_sigmask; then echo "Test failed; some signals are blocked that shouldn't be." OUTCOME=1 else OUTCOME=0 fi rm -f ./check_sigmask check_sigmask.c exit $OUTCOME-1signals_unblocked_tmpdirqmtest-2.4.1/tests/xmldb/signals_unblocked_tmpdir.qma0000664000076400007640000000063511107032176022406 0ustar stefanstefan temp_dir_path1qmtest-2.4.1/tests/xmldb/test.qms/0000775000076400007640000000000011122067201016405 5ustar stefanstefanqmtest-2.4.1/tests/xmldb/test.qms/classes.qms/0000775000076400007640000000000011122067201020641 5ustar stefanstefanqmtest-2.4.1/tests/xmldb/test.qms/classes.qms/tempdir1.qma0000664000076400007640000000054311107032176023076 0ustar stefanstefan temporary.TempDirectoryResource qmtest-2.4.1/tests/xmldb/test.qms/classes.qms/scripttest_closes_stdin.qmt0000664000076400007640000000176311107032176026356 0ustar stefanstefan fooGoing to read, expecting data Read foo Going to read, expecting nothing Read echo "Going to read, expecting data" read FOO echo "Read $FOO" echo "Going to read, expecting nothing" read BAR echo "Read $BAR".*05qmtest-2.4.1/tests/xmldb/test.qms/classes.qms/tempdir1.qmt0000664000076400007640000000115511107032176023121 0ustar stefanstefan python.ExecTest import os.path # The resource 'tempdir1' created a temporary directory for us. dir_path = context["temp_dir_path"] # The directory should exist. assert os.path.isdir(dir_path) # The directory should be empty. assert len(os.listdir(dir_path)) == 0 1 test.classes.tempdir1 qmtest-2.4.1/tests/xmldb/test.qms/classes.qms/scripttest1.qmt0000664000076400007640000000141211107032176023655 0ustar stefanstefan command.ShellScriptTest 0 MY_ENV_VAR=Hello .* # Make sure the environment variable is set correctly. test ${MY_ENV_VAR} = "Hello" qmtest-2.4.1/tests/xmldb/api.qms/0000775000076400007640000000000011122067201016177 5ustar stefanstefanqmtest-2.4.1/tests/xmldb/api.qms/test.qms/0000775000076400007640000000000011122067201017755 5ustar stefanstefanqmtest-2.4.1/tests/xmldb/api.qms/test.qms/fields.qmt0000664000076400007640000000215711107032176021761 0ustar stefanstefan .* """This test verifies that the 'Field' argument processing by means of Extension.Type works correctly.""" from qm.fields import * from qm.extension import * dir(Extension) dir(TextField) class FieldTester(Extension): text = TextField(name = 'foo', default_value = "argument") number = IntegerField(default_value = 42) boolean = BooleanField(default_value = True) tuple_ = TupleField(fields = (TextField(default_value = "text"), IntegerField(default_value = 42))) set_ = SetField(TextField()) attachment = AttachmentField() enum = EnumerationField(default_value = "no", enumerals = ["yes", "no"]) f = FieldTester(text = "Hello world !", boolean = False) assert f.text == "Hello world !" assert f.number == 42 assert f.boolean == False assert f.tuple_ == ["text", 42] assert f.set_ == [] assert f.enum == "no" qmtest-2.4.1/tests/xmldb/api.qms/test.qms/derived.qmt0000664000076400007640000000035711107032176022135 0ustar stefanstefan .*qmtest-2.4.1/tests/xmldb/api.qms/test.qms/test_interface.qmt0000664000076400007640000000036311107032176023507 0ustar stefanstefan .*qmtest-2.4.1/tests/xmldb/common.qms/0000775000076400007640000000000011122067201016716 5ustar stefanstefanqmtest-2.4.1/tests/xmldb/common.qms/parser_help.qmt0000664000076400007640000000326611107032176021762 0ustar stefanstefan python.ExecTest import qm.cmdline name = 'qmtrack' option_a = ('a', 'a_option', None, 'Option A Description') option_b = ('b', 'b_option', 'foo', 'Option B Description') option_c = ('c', 'c_option', None, 'Option C Description') option_d = ('d', 'd_option', None, 'Option D Description') option_e = ('e', 'e_option', None, 'Option E Description') option_f = ('f', 'f_option', None, 'Option F Description') command_1 = ('create', 'Create an issue', 'name', "This command will create an issue. _name_ is the" " name of the issue to be created.", [option_d]) command_2 = ('edit', 'Edit an issue', 'issue field1=foo field2+=bar', "This command will edit an issue. _issue_ is the" " name of the issue to be edited. field1, field2,..." " are the fields to be edited.", [option_e]) command_3 = ('join', 'Join two issues', 'issue1 issue2', "This command will join two issues. _issue1_ and" " _issue2_ are the two issues to be joined.", [option_f]) options = [ option_a, option_b, option_c ] commands = [ command_1, command_2, command_3 ] parser = qm.cmdline.CommandParser(name, options, commands) parser.GetBasicHelp() parser.GetCommandHelp("create") parser.GetCommandHelp("edit") parser.GetCommandHelp("join") 1 common.parser_create qmtest-2.4.1/tests/xmldb/common.qms/parser_parse.qmt0000664000076400007640000000410711107032176022137 0ustar stefanstefan python.ExecTest import qm.cmdline name = 'qmtrack' option_a = ('a', 'a_option', None, 'Option A Description') option_b = ('b', 'b_option', 'foo', 'Option B Description') option_c = ('c', 'c_option', None, 'Option C Description') option_d = ('d', 'd_option', None, 'Option D Description') option_e = ('e', 'e_option', None, 'Option E Description') option_f = ('f', 'f_option', None, 'Option F Description') command_1 = ('create', 'Create an issue', 'name', "This command will create an issue. _name_ is the" " name of the issue to be created.", [option_d]) command_2 = ('edit', 'Edit an issue', 'issue field1=foo field2+=bar', "This command will edit an issue. _issue_ is the" " name of the issue to be edited. field1, field2,..." " are the fields to be edited.", [option_e]) command_3 = ('join', 'Join two issues', 'issue1 issue2', "This command will join two issues. _issue1_ and" " _issue2_ are the two issues to be joined.", [option_f]) options = [ option_a, option_b, option_c ] commands = [ command_1, command_2, command_3 ] parser = qm.cmdline.CommandParser(name, options, commands) command_line = [ '-b', 'foo', '--a_option', 'edit', '--e_option', 'issue1', 'issue2' ] parsed_line = parser.ParseCommandLine(command_line) parsed_line[0][0][0] == 'b_option' \ and parsed_line[0][0][1] == 'foo' \ and parsed_line[0][1][0] == 'a_option' \ and parsed_line[0][1][1] == '' \ and parsed_line[1] == 'edit' \ and parsed_line[2][0][0] == 'e_option' \ and parsed_line[2][0][1] == '' \ and parsed_line[3][0] == 'issue1' \ and parsed_line[3][1] == 'issue2' common.parser_create qmtest-2.4.1/tests/xmldb/common.qms/parse_time1.qmt0000664000076400007640000000061611107032176021663 0ustar stefanstefan python.ExecTest from qm.common import parse_time parse_time("1970-01-01 00:00 UTC") == 0 qmtest-2.4.1/tests/xmldb/common.qms/parse_time3.qmt0000664000076400007640000000072711107032176021670 0ustar stefanstefan python.ExecTest from qm.common import format_time, parse_time format_time(parse_time("1973-12-03 16:30 UTC"), local_time_zone=0) \ == "1973-12-03 16:30 UTC" qmtest-2.4.1/tests/xmldb/common.qms/label_is_valid.qmt0000664000076400007640000000137011107032176022401 0ustar stefanstefan python.ExecTest def is_valid(l): from python_label import PythonLabel return PythonLabel("").IsValid(l, 1) is_valid("abcde") \ and is_valid("ab_xz_efg_0912_bjd__f_") \ and is_valid("_foo_bar") \ and not is_valid("") \ and not is_valid("Hello") \ and not is_valid("hello world") qmtest-2.4.1/tests/xmldb/common.qms/parser_two_char_short.qmt0000664000076400007640000000127311107032176024053 0ustar stefanstefan python.ExceptionTest import qm.cmdline option_a = ('aa', 'a_option', None, 'Option A Description') qm.cmdline.CommandParser('qmtrack', [option_a], []) ValueError 'short option must have exactly 1 character' qmtest-2.4.1/tests/xmldb/common.qms/format_time1.qmt0000664000076400007640000000064311107032176022041 0ustar stefanstefan python.ExecTest import qm.common qm.common.format_time(0, local_time_zone=0) \ == "1970-01-01 00:00 UTC" qmtest-2.4.1/tests/xmldb/common.qms/parser_dup_command_long.qmt0000664000076400007640000000167311107032176024337 0ustar stefanstefan python.ExceptionTest import qm.cmdline option_d = ('d', 'd_option', None, 'Option D Description') option_e = ('e', 'd_option', None, 'Option E Description') command_1 = ('create', 'Create an issue', 'name', "This command will create an issue. _name_ is the" " name of the issue to be created.", [option_d, option_e]) qm.cmdline.CommandParser('qmtrack', [], [command_1]) ValueError 'duplicate long command option --d_option' qmtest-2.4.1/tests/xmldb/common.qms/parse_time4.qmt0000664000076400007640000000173411107032176021670 0ustar stefanstefan python.ExecTest # Format 'time' (in seconds) as a timestamp, then convert it # back to seconds. Return the difference between 'time' # and this result. Since the timestamp format has one-minute # precision, this result could normally be as much as 60 # seconds off. def delta(time): from qm.common import format_time, parse_time new_time = parse_time(format_time(time)) return new_time - time # Run 'delta' on several different times. deltas = map(delta, [0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 100000000]) # Look for cases differing by more than a minute. deltas = filter(lambda d: d >= 60, deltas) len(deltas) == 0 qmtest-2.4.1/tests/xmldb/common.qms/parser_no_long.qmt0000664000076400007640000000125411107032176022460 0ustar stefanstefan python.ExceptionTest import qm.cmdline option_a = ('a', '', None, 'Option A Description') qm.cmdline.CommandParser('qmtrack', [option_a], []) ValueError 'long option must be specified for -a' qmtest-2.4.1/tests/xmldb/common.qms/parse_time2.qmt0000664000076400007640000000065411107032176021666 0ustar stefanstefan python.ExecTest from qm.common import parse_time parse_time("1970-01-01 00:00", default_local_time_zone=0) \ == 0 qmtest-2.4.1/tests/xmldb/common.qms/label_thunk.qmt0000664000076400007640000000157611107032176021750 0ustar stefanstefan python.ExecTest import qm.label def is_valid(l): from python_label import PythonLabel return PythonLabel("").IsValid(l, 1) is_valid(qm.label.thunk("abcyz_12390_")) \ and is_valid(qm.label.thunk(" abc 123 ")) \ and is_valid(qm.label.thunk("hello world!")) \ and is_valid(qm.label.thunk("(*@KAJD)92809 kj!")) \ and is_valid(qm.label.thunk("____foo bar____")) \ and is_valid(qm.label.thunk("This is a test.")) qmtest-2.4.1/tests/xmldb/common.qms/parser_dup_command_short.qmt0000664000076400007640000000166411107032176024537 0ustar stefanstefan python.ExceptionTest import qm.cmdline option_d = ('d', 'd_option', None, 'Option D Description') option_e = ('d', 'e_option', None, 'Option E Description') command_1 = ('create', 'Create an issue', 'name', "This command will create an issue. _name_ is the" " name of the issue to be created.", [option_d, option_e]) qm.cmdline.CommandParser('qmtrack', [], [command_1]) ValueError 'duplicate short command option -d' qmtest-2.4.1/tests/xmldb/common.qms/parser_create.qmt0000664000076400007640000000300111107032176022260 0ustar stefanstefan python.ExecTest import qm.cmdline name = 'qmtrack' option_a = ('a', 'a_option', None, 'Option A Description') option_b = ('b', 'b_option', 'foo', 'Option B Description') option_c = ('c', 'c_option', None, 'Option C Description') option_d = ('d', 'd_option', None, 'Option D Description') option_e = ('e', 'e_option', None, 'Option E Description') option_f = ('f', 'f_option', None, 'Option F Description') command_1 = ('create', 'Create an issue', 'name', "This command will create an issue. _name_ is the" " name of the issue to be created.", [option_d]) command_2 = ('edit', 'Edit an issue', 'issue field1=foo field2+=bar', "This command will edit an issue. _issue_ is the" " name of the issue to be edited. field1, field2,..." " are the fields to be edited.", [option_e]) command_3 = ('join', 'Join two issues', 'issue1 issue2', "This command will join two issues. _issue1_ and" " _issue2_ are the two issues to be joined.", [option_f]) options = [ option_a, option_b, option_c ] commands = [ command_1, command_2, command_3 ] parser = qm.cmdline.CommandParser(name, options, commands) 1 qmtest-2.4.1/tests/xmldb/QMTest/0000775000076400007640000000000011122067201016004 5ustar stefanstefanqmtest-2.4.1/tests/xmldb/QMTest/test_interface.py0000664000076400007640000000315311107032176021365 0ustar stefanstefan######################################################################## # # File: test_interface.py # Author: Mark Mitchell # Date: 10/15/2002 # # Contents: # TestInterface test class. # # Copyright (c) 2002 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## from qm.test.database import Database from qm.test.test import Test import types ######################################################################## # Classes ######################################################################## class TestInterface(Test): """A 'TestInterface' test tests the interface of the 'Test' class. The 'TestInterface' test class is desiged to ensure that the interface to test classes does not change.""" def __init__(self, arguments, **extras): """Construct a new 'TestInterface'.""" # Even though this constructor just passes along its # arguments, it makes sure that no changes in the interface to # the constructor take place. Test.__init__(self, arguments, **extras) def Run(self, context, result): try: if not isinstance(self.GetId(), types.StringType): result.Fail("GetId() did not return a string.") if not isinstance(self.GetDatabase(), Database): result.Fail("GetDatabase() did not return a Database.") except: result.NoteException(outcome = Result.FAIL) qmtest-2.4.1/tests/xmldb/QMTest/classes.qmc0000664000076400007640000000024411107032176020151 0ustar stefanstefan test_interface.TestInterfacetest_inheritance.Derivedqmtest-2.4.1/tests/xmldb/QMTest/test_interface.pyc0000664000076400007640000000270211120047561021526 0ustar stefanstefan ~4Ic@sFddklZddklZddkZdefdYZdS(i(tDatabase(tTestNt TestInterfacecBs eZdZdZdZRS(sA 'TestInterface' test tests the interface of the 'Test' class. The 'TestInterface' test class is desiged to ensure that the interface to test classes does not change.cKsti|||dS(s Construct a new 'TestInterface'.N(Rt__init__(tselft argumentstextras((s=/home/stefan/work/qmtest/tests/xmldb/QMTest/test_interface.pyR scCsvyUt|itip|idnt|itp|idnWn|idti nXdS(Ns GetId() did not return a string.s(GetDatabase() did not return a Database.toutcome( t isinstancetGetIdttypest StringTypetFailt GetDatabaseRt NoteExceptiontResulttFAIL(Rtcontexttresult((s=/home/stefan/work/qmtest/tests/xmldb/QMTest/test_interface.pytRun)s(t__name__t __module__t__doc__RR(((s=/home/stefan/work/qmtest/tests/xmldb/QMTest/test_interface.pyRs (tqm.test.databaseRt qm.test.testRR R(((s=/home/stefan/work/qmtest/tests/xmldb/QMTest/test_interface.pyts qmtest-2.4.1/tests/xmldb/QMTest/configuration0000664000076400007640000000044611107032176020610 0ustar stefanstefan qm.test.xmldb.Database qmtest-2.4.1/tests/xmldb/QMTest/test_inheritance.py0000664000076400007640000000277111107032176021723 0ustar stefanstefan######################################################################## # # File: test_inheritance.py # Author: Mark Mitchell # Date: 12/20/2002 # # Contents: # TestInheritance test class. # # Copyright (c) 2002 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## import qm.extension import qm.fields from qm.test.test import Test ######################################################################## # Classes ######################################################################## class Base(Test): """A 'Base' has one test argument.""" arguments = [ qm.fields.IntegerField(name = "a") ] class Derived(Base): """A 'Derived' overrides the argument from 'Base'.""" arguments = [ qm.fields.IntegerField(name = "a", computed = "true") ] b = qm.fields.IntegerField(name = "b", default_value = 42) def Run(self, context, result): args = qm.extension.get_class_arguments_as_dictionary(Derived) if args['a'] != Derived.arguments[0]: result.Fail("Incorrect argument.") elif not args['a'].IsComputed(): result.Fail("Argument is not computed.") elif self.b != args['b'].GetDefaultValue(): result.Fail("Argument 'b' has wrong value.") qmtest-2.4.1/tests/xmldb/QMTest/test_inheritance.pyc0000664000076400007640000000306111120047561022056 0ustar stefanstefan ~4Ic@sXddkZddkZddklZdefdYZdefdYZdS(iN(tTesttBasecBs&eZdZeiiddgZRS(sA 'Base' has one test argument.tnameta(t__name__t __module__t__doc__tqmtfieldst IntegerFieldt arguments(((s?/home/stefan/work/qmtest/tests/xmldb/QMTest/test_inheritance.pyRstDerivedcBsPeZdZeiiddddgZeiiddddZdZRS( s/A 'Derived' overrides the argument from 'Base'.RRtcomputedttruetbt default_valuei*cCstiit}|dtidjo|idnN|dip|idn,|i|dijo|idndS(NRisIncorrect argument.sArgument is not computed.RsArgument 'b' has wrong value.( Rt extensiont!get_class_arguments_as_dictionaryR R tFailt IsComputedRtGetDefaultValue(tselftcontexttresulttargs((s?/home/stefan/work/qmtest/tests/xmldb/QMTest/test_inheritance.pytRun-s( RRRRRR R RR(((s?/home/stefan/work/qmtest/tests/xmldb/QMTest/test_inheritance.pyR #s  (t qm.extensionRt qm.fieldst qm.test.testRRR (((s?/home/stefan/work/qmtest/tests/xmldb/QMTest/test_inheritance.pyts   qmtest-2.4.1/tests/results_files/0000775000076400007640000000000011122067201016404 5ustar stefanstefanqmtest-2.4.1/tests/results_files/README0000664000076400007640000000322011107032175017266 0ustar stefanstefanWe have had several different result file formats, and we need to be able to load all of them. Listed in the order QMTest was changed to output each format. -- XML result file format. The original format. -> xml_results.qmr -- Pickle format v0 (original format). -- 'Result's still contain the context they were run in. -- just a bunch of 'Result' pickles, no metadata. -- 'Result's still use the standard pickling mechanism. -> result_class_v0-file_format_v0-pickling_format_v0.qmr -- Pickle format v0 with new 'Result' object. -- 'Result's no longer contain the context object they were run in. -- just a bunch of 'Result' pickles, no metadata. -- 'Result's still use the standard pickling mechanism. -> result_class_v1-file_format_v0-pickling_format_v0.qmr -- Pickle format v1 with new 'Result' object. -- 'Result's no longer contain the context object they were run in. -- More complicated file layout containing metadata. -- 'Result's still use the standard pickling mechanism. -> result_class_v1-file_format_v1-pickling_format_v0.qmr -- Pickle format v1 with new 'Result' object and new 'Result' pickling. -- 'Result's no longer contain the context object they were run in. -- More complicated file layout containing metadata. -- 'Result's no longer use the standard pickling mechanism. -> result_class_v1-file_format_v1-pickling_format_v1.qmr -- XML result file format v2. -> xml_results_v2.qmr -- XML result file format v3. -- The 'outcome' is now provided as an attribute of the 'result' element. -> xml_results_v3.qmr qmtest-2.4.1/tests/results_files/xml_results_v2.qmr0000664000076400007640000000510511107032175022123 0ustar stefanstefan 2003-09-22T01:43:05Z ERROR "Exception evaluating expression." "exceptions.SyntaxError: invalid syntax (line 1)" "local" "<pre> File "/home/mitchell/dev/qm-mainline/qm/test/classes/python.py", line 101, in Run global_namespace, local_namespace) </pre>" FAIL "0" "0" "Expression evaluates to false." "local" PASS "local" FAIL "0" "0" "Expression evaluates to false." "local" PASS "local" UNTESTED "A prerequisite produced an incorrect outcome." "PASS" "FAIL" "fail" PASS "local" 2003-09-22T01:43:05Z qmtest-2.4.1/tests/results_files/xml_results_v3.qmr0000664000076400007640000000616511107032175022133 0ustar stefanstefan 2003-10-01T19:15:09Z "Exception evaluating expression." "exceptions.SyntaxError: invalid syntax (line 1)" "local" "<pre> File "/usr/local/share/qm/test/classes/python.py", line 101, in Run global_namespace, local_namespace) </pre>" "0" "0" "Expression evaluates to false." "local" "local" "0" "0" "Expression evaluates to false." "local" "local" "A prerequisite produced an incorrect outcome." "PASS" "FAIL" "fail" "local" --- STATISTICS --------------------------------------------------------------- 5 tests total 1 ( 20%) tests ERROR 2 ( 40%) tests FAIL 1 ( 20%) tests UNTESTED 1 ( 20%) tests PASS --- TESTS THAT DID NOT PASS -------------------------------------------------- error : ERROR Exception evaluating expression. fail : FAIL Expression evaluates to false. fail_with_tmpdir : FAIL Expression evaluates to false. untested : UNTESTED A prerequisite produced an incorrect outcome. 2003-10-01T19:15:09Z qmtest-2.4.1/tests/results_files/result_class_v1-file_format_v1-pickling_format_v0.qmr0000664000076400007640000000273711107032175030722 0ustar stefanstefanK. N.N(U annotationqU qmtest_pathqU../../../install/bin/qmtestqt.N.(U annotationqUqmtest.run.start_timeqU2003-08-08T23:03:19Zqt.(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeq UUNTESTEDq U_Result__annotationsq }q (U qmtest.causeq UCould not load test.qUqmtest.tracebackqT
  File "/lib/python2.2/site-packages/qm/test/execution_engine.py", line 200, in _RunTests

  File "/lib/python2.2/site-packages/qm/test/file_database.py", line 60, in GetTest

  File "/lib/python2.2/site-packages/qm/test/classes/xml_database.py", line 68, in _GetTestFromPath
Uqmtest.exceptionqUxml_database.TestFileError: A problem occurred while loading the XML test file "untested": argument 3 to map() must support iteration.uU _Result__idqUuntestedqub.(hoq}q(hhh UERRORqh }q(h U Exception evaluating expression.qU qmtest.targetqUlocalqhU]
  File "/lib/python2.2/site-packages/qm/test/classes/python.py", line 101, in Run
hU/exceptions.SyntaxError: invalid syntax (line 1)uhUerrorqub.(hoq}q(hhh UFAILqh }q(UExecTest.valueqU0h UExpression evaluates to false.q hhU ExecTest.exprq!X0uhUfailq"ub.(hoq#}q$(hUresource_setupq%h UPASSq&h }q'hhshXtmpdir_resourceq(ub.(hoq)}q*(hhh hh }q+(hU0h h hhh!X0uhUfail_with_tmpdirq,ub.(hoq-}q.(hhh h&h }q/hhshUpassq0ub.(hoq1}q2(hUresource_cleanupq3h h&h }q4hhshh(ub.N.(U annotationqUqmtest.run.end_timeqU2003-08-08T23:03:19Zqt.qmtest-2.4.1/tests/results_files/tdb/0000775000076400007640000000000011122067201017155 5ustar stefanstefanqmtest-2.4.1/tests/results_files/tdb/fail.qmt0000664000076400007640000000072711107032174020625 0ustar stefanstefan pass.*0qmtest-2.4.1/tests/results_files/tdb/untested.qmt0000664000076400007640000000102611107032174021536 0ustar stefanstefan failPASSpass.*1 qmtest-2.4.1/tests/results_files/tdb/tmpdir_resource.qma0000664000076400007640000000064511107032174023074 0ustar stefanstefan temp_dir_path1qmtest-2.4.1/tests/results_files/tdb/pass.qmt0000664000076400007640000000072711107032174020660 0ustar stefanstefan pass.*1qmtest-2.4.1/tests/results_files/tdb/QMTest/0000775000076400007640000000000011122067201020332 5ustar stefanstefanqmtest-2.4.1/tests/results_files/tdb/QMTest/configuration0000664000076400007640000000033411107032174023130 0ustar stefanstefan qmtest-2.4.1/tests/results_files/tdb/fail_with_tmpdir.qmt0000664000076400007640000000077111107032174023236 0ustar stefanstefan pass.*0tmpdir_resource qmtest-2.4.1/tests/results_files/tdb/error.qmt0000664000076400007640000000076411107032174021044 0ustar stefanstefan pass.*raise "An exception"qmtest-2.4.1/tests/results_files/result_class_v1-file_format_v0-pickling_format_v0.qmr0000664000076400007640000000174711107032175030721 0ustar stefanstefan(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeqUERRORqU_Result__annotationsq}q (U qmtest.causeq U Exception evaluating expression.q U qmtest.targetq Ulocalq Uqmtest.tracebackqU
  File "/home/njs/src/cvs/qm/qm-old-2/qm/test/classes/python.py", line 101, in Run
    global_namespace, local_namespace)
Uqmtest.exceptionqU/exceptions.SyntaxError: invalid syntax (line 1)uU _Result__idqUerrorqub.(hoq}q(hhhUFAILqh}q(UExecTest.valueqU0h UExpression evaluates to false.qh h U ExecTest.exprqX0uhUfailqub.(hoq}q(hhhUUNTESTEDqh}q(h U-A prerequisite produced an incorrect outcome.qUqmtest.expected_outcomeqXPASSq Uqmtest.prequisiteq!hUqmtest.outcomeq"huhUuntestedq#ub.(hoq$}q%(hUresource_setupq&hUPASSq'h}q(h h shXtmpdir_resourceq)ub.(hoq*}q+(hhhhh}q,(hU0h hh h hX0uhUfail_with_tmpdirq-ub.(hoq.}q/(hhhh'h}q0h h shUpassq1ub.(hoq2}q3(hUresource_cleanupq4hh'h}q5h h shh)ub.qmtest-2.4.1/tests/results_files/QMTest/0000775000076400007640000000000011122067201017561 5ustar stefanstefanqmtest-2.4.1/tests/results_files/QMTest/classes.qmc0000664000076400007640000000027711107032175021733 0ustar stefanstefan results_file_database.ResultsFileDatabaseresults_file_test.ResultsFileTest qmtest-2.4.1/tests/results_files/QMTest/results_file_database.pyc0000664000076400007640000000514511120047551024633 0ustar stefanstefan }4Ic@s<ddkZddkZddkTdefdYZdS(iN(t*tResultsFileDatabasecBs/eZdZdZdZdddZRS(sDatabase storing result file tests for QMTest. Each file in the test directory matching the glob "*.qmr" is considered to be a test, and should be a results file resulting from running the database "tdb" in the test directory. So to generate a new test, one generally should run "qmtest -D tdb run -o my_test". Each test is considered to pass if the latest version of qmtest is able to load it in as an expectations file and run with no unexpected results. This database is read-only, i.e. the methods to update it through the GUI are not implemented. It is expected that users will update it by creating new result files automatically. Currently, there are no subdirectories and no resources in this database.cCs!d|ds   qmtest-2.4.1/tests/results_files/QMTest/configuration0000664000076400007640000000014511107032175022360 0ustar stefanstefan qmtest-2.4.1/tests/results_files/QMTest/results_file_test.pyc0000664000076400007640000000412411120047557024050 0ustar stefanstefan }4Ic@sRddkZddkZddkZddkTddkTdefdYZdS(iN(t*tResultsFileTestc BsqeZdZeiiddddddddd d eiidd dd ddddd d gZdZRS(sCA 'ResultsFileTest' tests that QMTest can load a results file. tnamet results_filettitlesPath to results file.tverbatimttruet multilinetfalset descriptions!The pathname of the results file.ttdbsPath to test database.sThe pathname of the test database file. All tests in this database will be run, and the outcomes compared to those stored in the results file.cCstii|ipttii|ipt|d}|d|idd|idf}tii }|i |}|i hdi |d6d|d 6|i |id 6|i |id 6|id jo|id n|o|idndS(Nt qmtest_paths-Dtruns-Os --no-outputt sselftest.RegTest.cmdlines%dsselftest.RegTest.exitcodesselftest.RegTest.stdoutsselftest.RegTest.stderrtsChild process reported errorss#Child process exited unsuccessfully(tostpathtisfileRtAssertionErrortisdirR tqmt executabletRedirectedExecutabletRuntAnnotatetjointQuotetstdouttstderrtFail(tselftcontexttresulttqmtesttargvtetstatus((sH/home/stefan/work/qmtest/tests/results_files/QMTest/results_file_test.pyR6s     (t__name__t __module__t__doc__Rtfieldst TextFieldt argumentsR(((sH/home/stefan/work/qmtest/tests/results_files/QMTest/results_file_test.pyRs   (Rtret qm.executableRt qm.test.testtqm.test.resulttTestR(((sH/home/stefan/work/qmtest/tests/results_files/QMTest/results_file_test.pyts     qmtest-2.4.1/tests/results_files/QMTest/results_file_database.py0000664000076400007640000000514411107032175024470 0ustar stefanstefan######################################################################## # # File: results_file_database.py # Author: Nathaniel Smith # Date: 2003-08-08 # # Contents: # ResultsFileDatabase. # # Copyright (c) 2003 by CodeSourcery, LLC. All rights reserved. # ######################################################################## ######################################################################## # Imports ######################################################################## import glob import os.path from qm.test.database import * ######################################################################## # Classes ######################################################################## class ResultsFileDatabase(Database): """Database storing result file tests for QMTest. Each file in the test directory matching the glob "*.qmr" is considered to be a test, and should be a results file resulting from running the database "tdb" in the test directory. So to generate a new test, one generally should run "qmtest -D tdb run -o my_test". Each test is considered to pass if the latest version of qmtest is able to load it in as an expectations file and run with no unexpected results. This database is read-only, i.e. the methods to update it through the GUI are not implemented. It is expected that users will update it by creating new result files automatically. Currently, there are no subdirectories and no resources in this database.""" def __init__(self, path, arguments): arguments["modifiable"] = "false" Database.__init__(self, path, arguments) def GetTest(self, test_id): results_file = os.path.join(self.GetPath(), test_id + ".qmr") if not os.path.exists(results_file): raise NoSuchTestError tdb = os.path.join(self.GetPath(), "tdb") return TestDescriptor(self, test_id, "results_file_test.ResultsFileTest", {"results_file": results_file, "tdb": tdb}) def GetIds(self, kind, directory = "", scan_subdirs = 1): assert directory == "" if kind == Database.TEST: p = self.GetPath() files = glob.glob(os.path.join(p, "*.qmr")) basenames = [os.path.basename(file) for file in files] names = [os.path.splitext(file)[0] for file in basenames] return names else: # There are no suites or resources in this database. return [] return ids qmtest-2.4.1/tests/results_files/QMTest/results_file_test.py0000664000076400007640000000542511107032175023705 0ustar stefanstefan######################################################################## # # File: results_file_test.py # Author: Nathaniel Smith # Date: 2003-08-08 # # Contents: # ResultsFileTest # # Copyright (c) 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## ######################################################################## # imports ######################################################################## import os import re import qm.executable from qm.test.test import * from qm.test.result import * ######################################################################## # classes ######################################################################## class ResultsFileTest(Test): """A 'ResultsFileTest' tests that QMTest can load a results file. """ arguments = [ qm.fields.TextField( name = "results_file", title = "Path to results file.", verbatim = "true", multiline = "false", description = """The pathname of the results file.""" ), qm.fields.TextField( name = "tdb", title = "Path to test database.", verbatim = "true", multiline = "false", description = """The pathname of the test database file. All tests in this database will be run, and the outcomes compared to those stored in the results file.""" ), ] def Run(self, context, result): # Sanity check the arguments. assert os.path.isfile(self.results_file) assert os.path.isdir(self.tdb) # The QMTest binary to test is specified as a context variable. qmtest = context['qmtest_path'] argv = (qmtest, "-D", self.tdb, "run", "-O", self.results_file, "--no-output") e = qm.executable.RedirectedExecutable() status = e.Run(argv) result.Annotate({ "selftest.RegTest.cmdline" : ' '.join(argv), "selftest.RegTest.exitcode" : ("%d" % status), "selftest.RegTest.stdout" : result.Quote(e.stdout), "selftest.RegTest.stderr" : result.Quote(e.stderr), }) if e.stderr != '': # Printing anything to stderr is a failure. result.Fail("Child process reported errors") elif status: # Unsuccessful termination is a failure. This is checked # second because output on stderr should come along with # an unsuccessful exit, and we want to pick the more specific # failure cause. result.Fail("Child process exited unsuccessfully") qmtest-2.4.1/tests/results_files/result_class_v0-file_format_v0-pickling_format_v0.qmr0000664000076400007640000000245511107032175030715 0ustar stefanstefan(cqm.test.result Result qoq}q(U _Result__kindqUtestqU_Result__outcomeqUERRORqU_Result__annotationsq}q (U qmtest.causeq U Exception evaluating expression.q U qmtest.targetq Ulocalq Uqmtest.tracebackqU
  File "/home/njs/src/cvs/qm/qm-old/qm/test/classes/python.py", line 101, in Run
    global_namespace, local_namespace)
Uqmtest.exceptionqU/exceptions.SyntaxError: invalid syntax (line 1)uU _Result__idqUerrorqU_Result__contextq(cqm.test.context Context qoq}q(U_Context__propertiesq}U_Context__temporariesq}ubub.(hoq}q(hhhUFAILqh}q(UExecTest.valueqU0h UExpression evaluates to false.qh h U ExecTest.exprqX0uhUfailqhhub.(hoq }q!(hhhUUNTESTEDq"h}q#(h U-A prerequisite produced an incorrect outcome.q$Uqmtest.expected_outcomeq%XPASSq&Uqmtest.prequisiteq'hUqmtest.outcomeq(huhUuntestedq)hhub.(hoq*}q+(hUresource_setupq,hUPASSq-h}q.h h shXtmpdir_resourceq/h(cqm.test.context ContextWrapper q0o}q1(U_ContextWrapper__addedq2}q3X temp_dir_pathq4U /tmp/@20284.1q5sU_ContextWrapper__contextq6hU_ContextWrapper__extraq7}ubub.(hoq8}q9(hhhhh}q:(hU0h hh h hX0uhUfail_with_tmpdirq;hhub.(hoq<}q=(hhhh-h}q>h h shUpassq?hhub.(hoq@}qA(hUresource_cleanupqBhh-h}qCh h shh/h(h0o}qD(h2}h6(ho}qE(h}h}ubh7}ubub.qmtest-2.4.1/tests/results_files/xml_results.qmr0000664000076400007640000000402011107032175021507 0ustar stefanstefan 2003-08-08T23:43:05Z ERRORException evaluating expression.exceptions.SyntaxError: invalid syntax (line 1)local<pre> File "/home/njs/src/cvs/qm/qm-pickle-compatibility/qm/test/classes/python.py", line 101, in Run global_namespace, local_namespace) </pre> FAIL00Expression evaluates to false.local PASSlocal FAIL00Expression evaluates to false.local PASSlocal UNTESTEDA prerequisite produced an incorrect outcome.PASSFAILfail PASSlocal 2003-08-08T23:43:05Z qmtest-2.4.1/tests/results_files/result_class_v1-file_format_v1-pickling_format_v1.qmr0000664000076400007640000000210111107032175030704 0ustar stefanstefanK. N.G(U annotationqU qmtest_pathqU../../qm/test/qmtestqt.N.(U annotationqUqmtest.run.start_timeqU2003-08-09T04:37:42Zqt.(cqm.test.result Result qoq(UtestqUerrorqUERRORq}q (U qmtest.causeq U Exception evaluating expression.q U qmtest.targetq Ulocalq Uqmtest.tracebackqU
  File "/home/njs/src/cvs/qm/qm-pickle-compatibility/qm/test/classes/python.py", line 101, in Run
    global_namespace, local_namespace)
Uqmtest.exceptionqU/exceptions.SyntaxError: invalid syntax (line 1)utb.(hoq(hUfailqUFAILq}q(UExecTest.valueqU0h UExpression evaluates to false.qh h U ExecTest.exprqX0utb.(hoq(Uresource_setupqXtmpdir_resourceqUPASSq}qh h stb.(hoq(hUfail_with_tmpdirqh}q(hU0h hh h hX0utb.(hoq(hUpassq h}q!h h stb.(hoq"(hUuntestedq#UUNTESTEDq$}q%(h U-A prerequisite produced an incorrect outcome.q&Uqmtest.expected_outcomeq'XPASSq(Uqmtest.prequisiteq)Xfailq*Uqmtest.outcomeq+hutb.(hoq,(Uresource_cleanupq-hh}q.h h stb.N.(U annotationqUqmtest.run.end_timeqU2003-08-09T04:37:42Zqt.qmtest-2.4.1/tests/QMTest/0000775000076400007640000000000011122067201014676 5ustar stefanstefanqmtest-2.4.1/tests/QMTest/classes.qmc0000664000076400007640000000016311107032202017031 0ustar stefanstefan selfdb.QMSelftestDatabase qmtest-2.4.1/tests/QMTest/rsh_target0000664000076400007640000000067011120047064016771 0ustar stefanstefansshlocalhostrshqmtest-2.4.1/tests/QMTest/configuration0000664000076400007640000000055511107032202017471 0ustar stefanstefan xmldbxmldb regressregress results_filesresults_files qmtest-2.4.1/tests/QMTest/thread_target0000664000076400007640000000061111120047561017441 0ustar stefanstefan4threadqmtest-2.4.1/tests/QMTest/process_target0000664000076400007640000000061611120047566017662 0ustar stefanstefan4processqmtest-2.4.1/share/0000775000076400007640000000000011122067201013461 5ustar stefanstefanqmtest-2.4.1/share/qmtest/0000775000076400007640000000000011122067201014776 5ustar stefanstefanqmtest-2.4.1/share/qmtest/web/0000775000076400007640000000000011122067201015553 5ustar stefanstefanqmtest-2.4.1/share/qmtest/web/stylesheets/0000775000076400007640000000000011122067201020127 5ustar stefanstefanqmtest-2.4.1/share/qmtest/web/stylesheets/qm.css0000664000076400007640000000557711107032173021277 0ustar stefanstefan/* Document body. */ body { margin-top: 16px; margin-left: 16px; margin-right: 16px; margin-bottom: 16px; color: black; background: white; font-family: arial,sans-serif; } body.help { margin-top: 8px; margin-left: 8px; margin-right: 8px; margin-bottom: 8px; color: black; background: #ffffd0; } body.popup { background: #c0c0c0; } /* Links. */ a:link { color: #500060; } a:visited { color: #500060; } a:active { color: #500060; } a:hover { color: #500060; } /* Menus. */ *.menu_bar, *.menu_item { background-color: #e8e8e8; } table.menu_bar { width: 100%; border-style: inset; border-width: thin; } a.menu_bar, a.menu_item { text-decoration: none; color: black; display: block; } a.menu_item { display: block; padding-left: 3px; padding-right: 3px; color: black; } a.menu_item:hover { background-color: #f0f8ff; } a.disabled_menu_item { background-color: #e8e8e8; display: block; padding-left: 3px; padding-right: 3px; color: gray; } div.menu { position: absolute; left: 0px; top: 0px; visibility: hidden; border-width: thin; border-style: inset; } /* Tables. */ /* Generic tables. */ th { text-align: left; } th.table_caption { text-align: center; } caption { text-align: center; font-weight: bold; } /* Tables are used sometimes used simply to control presentation. The "data" class indicates that the table is being used to display tabular data. */ table.data { margin: 4px; padding: 4px; } th.issue-class { background-color: #e0e0e0; color: black; text-align: left; font-weight: bold; } span#colhead { background-color: black; color: white; } a#colhead { color: white; background-color: black; } a.reverse { color: white; background-color: black; } span.fieldname { font-weight: bold; } span#button { color: red; background-color: black; } span.error, span.warning { color: #c00000; } *.field { background-color: #f0f8ff; } tr.field-error { background-color: #fff0f8; } tr.form-submit { background-color: #f8ffe8; } tr.heading { background-color: #e8e8e8; } span.userid { color: #102050; } a.userid { color: #a0a0cf; } a.help-link { font-size: xx-small; color: #402090; } input.submit { background-color: #e0e0e0; } span.outcome { font-weight: bold; } span.cause { font-style: italic; } span.id { font-family: monospace; font-weight: bold; } /* Test outcomes. */ .qmtest_pass { background-color: #a0f0a0; } .qmtest_fail, .qmtest_unexpected { background-color: #ff9090; } .qmtest_error { background-color: #ffffe0; } .qmtest_untested { background-color: #d0d0d0; } .qmtest_expected { background-color: #c0c0c0; } .qmtest_mixed { background-color: #ffaaff; } qmtest-2.4.1/share/qmtest/web/common.js0000664000076400007640000003004211107032173017403 0ustar stefanstefan//////////////////////////////////////////////////////////////////////// // // File: common.js // Author: Alex Samuel // Date: 2001-06-09 // // Contents: // Common JavaScript functions for web pages. // // Copyright (c) 2001, 2002 by CodeSourcery, LLC. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation files // (the "Software"), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. // //////////////////////////////////////////////////////////////////////// // Remove the select item from a set control. // // 'select' -- The select input displaying the elements in the set. // // 'contents' -- The hidden input that contains the encoded contents of // the set. function remove_from_set(select, contents) { // Is anything selected? if(select.selectedIndex != -1) // Yes. Drop it from the options list. select.options[select.selectedIndex] = null; // Re-encode the set contents. contents.value = encode_select_options(select); return false; } // Add an element to a set control. // // 'select' -- The select input displaying the elements in the set. // // 'contents' -- The hidden input that contains the encoded contents of // the set. // // 'text' -- The user-visible text representing the element to add to // the set. // // 'value' -- The encoded value representing the element to add to the // set. // // The new element is not added if there is already another element in // the set with the same encoded value. function add_to_set(select, contents, text, value) { var options = select.options; // Look for another option that has the same value. for(var i = 0; i < options.length; ++i) if(options[i].value == value) // Found a match; don't continue. return false; // Append a new option, if the value is not empty. if(value != "") options[options.length] = new Option(text, value); // Re-encode the set contents. contents.value = encode_select_options(select); return false; } // Move the selected element in a set control. // // 'select' -- The select input displaying the elements in the set. // // 'contents' -- The hidden input that contains the encoded contents of // the set. // // 'offset' -- The number of positions by which to move the selected // element. Negative values move the element towards the beginning of // the set. function move_in_set(select, contents, offset) { swap_option(select, offset); contents.value = encode_select_options(select); } // Encode the values of the options in a set control. // // 'select' -- The select input displaying the elements in the set. // // returns -- A string containing the value of the options of 'select', // separated by commas. function encode_select_options(select) { // Construct the encoded value in this variable. var result = ""; // Loop over options in the select list. for(var i = 0; i < select.options.length; ++i) { // Elements after the first are preceded by commas. if(i > 0) result += ","; // Append the next value. result += select.options[i].value; } return result; } function update_from_select(select, control) { if(select.selectedIndex != -1) control.value = select.options[select.selectedIndex].value; } var help_window = null; function show_help(help_page) { if(help_window != null && !help_window.closed) help_window.close(); help_window = window.open("", "help", "resizable,scrollbars"); help_window.document.open("text/html", "replace"); help_window.document.write(help_page); help_window.document.close(); } var debug_window = null; function debug(msg) { if(debug_window == null || debug_window.closed) { debug_window = window.open("", "debug", "resizable"); debug_window.document.open("text/plain", "replace"); } debug_window.document.writeln(msg); } function move_option(src, dst) { if(src.selectedIndex == -1) return; var option = src[src.selectedIndex]; dst[dst.length] = new Option(option.text, option.value); src[src.selectedIndex] = null; } function swap_option(select, offset) { var index = select.selectedIndex; if(index == -1) return; var new_index = index + offset; if(new_index < 0 || new_index >= select.length) return; var text = select[index].text; var value = select[index].value; select[index].text = select[new_index].text; select[index].value = select[new_index].value; select[new_index].text = text; select[new_index].value = value; select.selectedIndex = new_index; } function popup_tutorial() { window.open("/tutorial/index.html", "tutorial", "resizable,toolbar,scrollbars"); } // Add or change a property in a property control. // // 'select' -- The select input displaying the properties. // // 'contents' -- The hidden input that gets the encoded representation // of the properties. // // 'name_text' -- The text input that displays the property name. // // 'value_text' -- The text input that displays the property value. // // If there already is a property named 'name', its value is replaced // with 'value'. Otherwise, a new property is added. // // See 'qm.web.make_properties_control'. function property_add_or_change(select, contents, name_text, value_text) { var name = name_text.value var value = value_text.value // No name? Bail. if(name == "") return; var options = select.options; // Construct the property as it will appear in the select input. var option_text = name + " = " + value; // Construct the encoded representation of the property. value = escape(value); var option_value = name + "=" + value; // Look for a existing property named 'name'. Scan over the contents // of the select input. for(var i = 0; i < options.length; ++i) { var option = options[i]; // Split the property name out of its encoded value. var option_name = option.value.split("=")[0]; // Does it match our name? if(option_name == name) { // Yes. Replace the property value with ours. option.text = option_text; option.value = option_value; // Reencode the properties. contents.value = encode_select_options(select); // Select the modified entry in the select input. options.selectedIndex = i; return; } } // Fell through; we didn't find a property matching 'name'. So, // add a new property. options[options.length] = new Option(option_text, option_value); // Reencode the properties. contents.value = encode_select_options(select); // Make the new property selected. options.selectedIndex = options.length - 1; // Clear out the name and value fields. name_text.value = "" value_text.value = "" return; } // Update the name and value inputs when a new property is selected. // // 'select' -- The select input displaying the properties. // // 'name_text' -- The text input that displays the property name. // // 'value_text' -- The text input that displays the property value. // // Sets the contents of 'name_text' and 'value_text' to the name and // value, respectively, of the property selected in 'select'. // // See 'qm.web.make_properties_control'. function property_update_selection(select, name_text, value_text) { var index = select.selectedIndex; if(index == -1) // No property is selected. return; // Get the encoded property from the select input. var option_value = select[index].value; // Extract the property name and value. var separator = option_value.indexOf("="); var name = option_value.substring(0, separator); var value = option_value.substring(separator + 1, option_value.length); value = unescape(value); // Set the text inputs appropriately. name_text.value = name; value_text.value = value; } // Remove the selected property in a property control. // // 'select' -- The select input displaying the properties. // // 'contents' -- The hidden input that gets the encoded representation // of the properties. // // 'name_text' -- The text input that displays the property name. // // 'value_text' -- The text input that displays the property value. // // 'button' -- The add/change button. // // See 'qm.web.make_properties_control'. function property_remove(select, contents, name_text, value_text, button) { // Is a property selected? if(select.selectedIndex != -1) { // Yes; remove it. select.options[select.selectedIndex] = null; // Re-encode the properties. contents.value = encode_select_options(select); // Clear out the name and value fields. name_text.value = ""; value_text.value = ""; // Make the button an 'Add' button. button.value = " Add "; } } // Display a popup message box. // // 'title' -- The box title. // // 'message' -- The message to display in the box. // // The box includes a single "Close" button. function popup_box(title, message) { var popup = window.open("", "popup", "width=480,height=200"); popup.document.open("text/html"); popup.document.write("" + title + "\n" + "" + "" + "

" + title + "

"); popup.document.write(message); popup.document.write("
" + "
" + "
\n"); popup.document.close(); } // Select an item in a select input by option value. // // 'select' -- The select input. // // 'value' -- The value of the option to be selected. // // Selects the first option whose value is 'value'. If there is none, // the selection is not changed. function select_item(select, value) { var i; for(i = 0; i < select.options.length; ++i) if(select.options[i].value == value) { select.selectedIndex = i; return; } } // Return the value of the option selected in a select input. // // 'select' -- The select input. // // Returns 'null' if no item is selected. function get_selected_value(select) { if(select.selectedIndex == -1) return null; else return select.options[select.selectedIndex].value; } // Return the absolute left coordinate of o. function get_left(o) { return (o.offsetParent == null ? o.offsetLeft : o.offsetLeft + get_left(o.offsetParent)); } // Return the absolute right coordinate of o. function get_right(o) { return get_left(o) + o.offsetWidth; } // Return the absolute top coordinate of o. function get_top(o) { return (o.offsetParent == null ? o.offsetTop : o.offsetTop + get_top(o.offsetParent)); } // Return the absolute bottom coordinate of o. function get_bottom(o) { return get_top(o) + o.offsetHeight; } // Return true if parent contains child. function is_parent_of(parent, child) { while (child) { if (child == parent) return true; child = child.parentNode; } return false; } //////////////////////////////////////////////////////////////////////// // Local Variables: // mode: java // indent-tabs-mode: nil // fill-column: 72 // End: qmtest-2.4.1/share/qmtest/web/images/0000775000076400007640000000000011122067201017020 5ustar stefanstefanqmtest-2.4.1/share/qmtest/web/images/right-arrow.gif0000664000076400007640000000011711107032173021756 0ustar stefanstefanGIF89a! , @x'Zd}b(faqT4QP;qmtest-2.4.1/share/qmtest/web/images/clear.gif0000664000076400007640000000005311107032173020576 0ustar stefanstefanGIF89a! ,L;qmtest-2.4.1/share/qmtest/web/images/logo.gif0000664000076400007640000000363211107032173020456 0ustar stefanstefanGIF89a# !""#$$$ %!&!%! &"!'#"'$#(#!)$!*%"*%#)%%-(%-)&.)',))/*(-)*.++.+,2-+3.+3/,0./2..40-51.61/720730:67<85>97>:7:7997;?;8:8<@<:B=;?=@>=C?>CHDBCBHEDHDDKOKHHHNLKNPLISPOUQOLLRNOUVRPWSQXTRXURYUSZWTXVV]YW\Z[YY^\Z\a^[b_]da^da_gdb``gfcdjfd`ajnkimllpmkromsonspntqogirfhtkluopuurptrrwtryvtzwv{xwps~|suyz~}vzťƨƨǩʯϥЦЩҪӭԯղбֶֶؽҷٸڹڻۼܽ,# H!1X@%7AHŋ3jQ´Tl {&P8ʜIMdp(Q<j F$tӧm&_":I5IdJ,To Kxd A+H3&WK*5$2 %Rur[2sAxUJ7a8j tjm0$ށŚ(69ЛN8 tN&ѷW|xuIxh$TM7hTmy(x 6x^yb' 9( aY542 m 1FBԄuE7 "Pcƈ@f_B9~Cy@3J9Ii[+ q&Hdݏ is1Ѝi~>'j!yُl$l JA. F 7y iBix{ hxi*!wq[$w| pEUYa@ |fjm{J;i4p%BDA@ {):Gx^ g_R */n5 ⋠ʛ/$dDܱ7[@+[L^s LXd]4<3DrOj7uS$Tв-H垜;P6gKb[Fqy" 5gElD-ixyݝ[$^j~dV]P s5A\am$W0o:*AڶzPdc:V#{J QzI hcw~o az KB\,/IBpDGw?9dstI/G7t7}ttHNW@1BB4?$#fe&H ,( T} 9B t#8$ yf4ll— OEz$Ȃ3R@ HśXaߐEqh\XP2&!BQfcjQ"x4rQ:9/W#B%`Q Mq^ HZ)7P@.Ɂ;qmtest-2.4.1/share/qmtest/web/images/left-arrow.gif0000664000076400007640000000011711107032173021573 0ustar stefanstefanGIF89a! , }x Iռ{9# dH)2S;qmtest-2.4.1/share/qmtest/messages/0000775000076400007640000000000011122067201016605 5ustar stefanstefanqmtest-2.4.1/share/qmtest/messages/diagnostics.txt0000664000076400007640000001641411107032172021665 0ustar stefanstefan######################################################################## # # File: diagnostics.txt # Author: Alex Samuel # Date: 2001-03-08 # # Contents: # QMTest diagnostic message templates. # # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## # Please keep diagnostics in alphabetical order by tag. @ action already exists There is already an action with ID "%(action_id)s". @ class not found QMTest could not find a class named "%(class_name)s". @ concurrency not integer The target concurrency "%(value)s" is not a positive integer. @ context property cannot be deleted The property %(property)s cannot be deleted from this context. @ could not load extension class The "%(class_name)s" extension class could not be loaded. @ could not load target file The "%(file)s" target file could not be loaded. @ db path doesn't exist "%(path)s" does not exist. @ db not modifiable The test database is not modifiable. @ dependency cycle This test depends on itself, either directly or by way of other tests. @ error loading xml resource A problem occurred while loading the XML resource file "%(resource_id)s": %(message)s @ error loading xml test A problem occurred while loading the XML test file "%(test_id)s": %(message)s @ execution terminated Termination was requested before this test was executed. @ extension class not found The extension class '%(klass)s' could not be found. You may need to set the 'QMTEST_CLASS_PATH' environment variable. @ extension class not subclass The %(kind)s extension class "%(class_name)s" is not a subclass of "%(base_name)s". @ failed prerequisite A prerequisite produced an incorrect outcome. @ failed resource Setup of a required resource failed. @ file invalid pattern The substitution pattern "%(pattern)s" is invalid: %(msg)s. The pattern should be a valid Python regular expression. @ file invalid substitution The substitution "%(substitution)s" is invalid. A substitution should have the form "/*pattern*/*replacement*/". @ invalid boolean context var The value of "%(key)s" is not a valid boolean value. @ invalid class There is no test class "%(class_name)s". @ invalid class name The class name "%(class_name)s" is invalid. Specify the class name in the form 'module.class'. @ invalid concurrency Specify a positive integer with the '--parallel' option. @ invalid context key The context key "%(key)s" is not valid. Context keys may contain letters, digits, hyphens, underscores, and periods. @ invalid environment assignment The string '%(assignment)s' is not a valid environment element. Environment elements must have the form 'variable=value'. @ invalid extension kind "%(kind)s" is not an extension class kind. The extension class kind must be one of "test", "resource", "database", or "target". @ invalid result The test %(id)s of class %(test_class)s returned an invalid result, '%(result)s'. @ invalid results file %(program_name)s could not open the test results file, %(path)s. The problem was: %(problem)s. @ invalid id The name "%(id)s" is not valid. Names may contain lower-case letters, digits, hyphens, underscores, and periods. @ invalid keyword assignment The option "%(argument)s" is not valid. This option should have the form KEY=VALUE. @ invalid results format "%(format)s" is not a valid format for test results. Possible formats are %(valid_formats)s. @ missing arg for template Specify the name of the test class and the test ID of the new test. @ missing argument A value for the "%(title)s" parameter is missing. @ missing context variable The context variable "%(key)s" was not defined. @ missing test id There is no test with ID "%(test_id)s". @ module does not exist There is no module named "%(module)s" in any of the extension directories. QMTest searched for files named '%(module)s.py', '%(module)s.pyc', and '%(module)s.pyo'. You may need to set the 'QMTEST_CLASS_PATH' environment variable. @ new db message QMTest has created a new test database at '%(path)s'. @ no db specified You must specify the location of the test database. * Specify the '--db-path' option with the path to the database. * Or, set the 'QMTEST_DB_PATH' environment variable to the path to the database. @ loading class QMTest will load '%(class_name)s' from '%(file_name)s'. @ no id for edit You must specify the ID of the item to edit. @ no id for show You must specify the ID of the item to show. @ no id for submit You must speicfy the ID of the item to submit. @ no results file specified You must specify a test run results file. @ no shell executable Cannot execute the shell interpreter. @ no such action There is no action with the action ID "%(action_id)s". @ no such ID There is no test or suite with ID "%(id)s". @ no such item There is no %(kind)s with the ID "%(item_id)s". @ no target for group No target which matches the group pattern specified for this test. @ not implemented An extension class failed to override the method "%(method_name)s". The following traceback may be helpful to the extension class implementor. @ not test database "%(path)s" is not a test database. @ prerequisite not in database The non-existant test "%(prerequisite)s" is listed as a prerequisite. @ seed not integer The random number generator seed you specified, "%(seed)s", is not an integer. @ suite already exists There is already a test suite with ID "%(suite_id)s". @ test already exists There is already a test with ID "%(test_id)s". @ test did not raise The test code did not raise an exception. @ test class not fully specified You must specify the Python path to the test class, including the packages or modules containig the class. For example, for test "MyTest" in module "mymod" of package "mypack", specify "mypack.mymod.MyTest". @ test raised non-object The test code raised an exception that isn't an exception object instance. The type of the exception was '%(exc_type)s'. @ test raised non-string The test code raised an exception that isn't a string. The type of the exception was '%(exc_type)s'. @ test raised wrong argument The test code raised an exception with an unexpected exception argument. @ test raised wrong class The test code raised an exception of the unexpected class type '%(class_name)s'. @ test raised wrong string The test code raised a string exception containing unexpected text "%(text)s". @ unexpected extension argument There is no "%(name)s" argument to the "%(class_name)s" extension class. @ unknown id in suite The ID "%(id)s" in suite "%(suite)s" does not exist. @ unknown test class The test class '%(test_class_name)s' of test "%(test_id)s" was not found. @ unknown test id There is no test with ID "%(test_id)s" in the database. @ unknown test or suite id There is no test or suite with ID "%(id)s" in the database. @ value provided for computed field A value was provided for the automatically computed argument "%(name)s" to the "%(class_name)s" extension class. @ xml invalid arg name %(name)s is not the name of an argument of this test class. @ xml not int value The text "%(value)s" is not an integer value. ######################################################################## # Local Variables: # mode: text # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/share/qmtest/messages/help.txt0000664000076400007640000002027611107032172020307 0ustar stefanstefan######################################################################## # # File: test-help.txt # Author: Alex Samuel # Date: 2001-04-20 # # Contents: # Common QMTest help message templates. # # Copyright (c) 2001, 2002 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## # Please keep diagnostics in alphabetical order by tag. @ category popup **Specify a Category** Enter the name of the category to which add the test. You may use any text string as the name of a category. @ categories control **Categories** The list displays the names of the categories of which this test is a member. To add this test to another category, click on *Add...*. To remove this test from a category, select the category's name in the list and click on *Remove.*. @ prerequisite popup **Specify a Prerequisite Test** Use this window to specify a test prerequisite. The prerequisite is a test that is run first, and it must produce an expected outcome for the prerequisite to be satisfied. To specify a prerequisite: 1. In the **Test ID** field, select the test ID of the prerequisite test from the list, or enter it in the text control. 2. In the **Expected Outcome** field, select the outcome that the prerequisite test must produce to satisfy the prerequisite. @ prerequisites control **Prerequisite Tests** The list displays the current prerequisites for this test, showing the test ID of each prerequisite test and its expected outcome. To add another prerequisite, click on *Add...*. To remove a prerequisite, select it in the list and click on *Remove*. @ resource class control **Resource Class** The "resource class" associated with a test indicates what kind of test it is. Select one of the available resource classes. If %(program_name)s cannot find a resource class that you think you have installed, you may need to set the 'QMTEST_CLASS_PATH' environment variable. This variable is like the 'PATH' environment variable, but contains a list of directories where %(program_name)s will look for resource classes. %(classes)s @ resource ID **Resource ID** An resource ID is a label that identifies an resource. Resource IDs are unique within a single test database, but are distinct from test IDs and suite IDs. The resource ID may be composed of lower-case letters, digits, hyphens, and underscores. You may optionally organize resources in a hierarchy using a period as the path separator. Bear in mind that a test's resources are always specified relative to the the test's path. For example, the test with ID "core.test1" would specify the resource "core.resource1" simply as "resource1". @ resource popup **Specify an Resource** Use this window to specify an resource for a test. An resource specifies a setup behavior that must be executed before the test is run, and/or a cleanup behavior that must be executed after the test is run. Resources are objects distinct from tests, but they reside in the same test database. Each resource has its own resource ID. Select an resource ID an existing resource from the list, or enter an resource ID in the edit control. @ resources control **Resources** The list displays the resource IDs of the resources specified for this test. To add another resource, click on *Add...*. To remove an resource, select it in the list and click on *Remove.*. @ suite ID **Test Suite ID** A test suite ID is a label that identifies a test suite. Test suite IDs are unique within a single test database, but are distinct from test IDs and resource IDs. The test suite ID may be composed of lower-case letters, digits, hyphens, and underscores. The IDs of tests in a test suite are specified relative to the test suite's ID. For instance, if your test database contains the tests * core.front_end.test1 * core.back_end.test2 and you create a test suite with ID "core.regression_tests" containing both tests, you specify the test IDs as "front_end.test1" and "back_end.test2". @ suite suite IDs **Suite IDs** The list displays the IDs of other test suites that are *explicitly* included in this test suite. When this test suite is run, %(program_name)s expands all included test suites recursively to determine the tests to run. A test suite displays included suite IDs relative to its own ID. For example, if the test suite "core.suite1" contains the suites "core.suite2" , the suite ID in this suite is specified as "suite2" . @ suite suite IDs control **Suite IDs** **Suite IDs** allows you to change the test suites that are *explicitly* included in this test suite. When this test suite is run, %(program_name)s expands all included test suites recursively to determine the tests to run. A test suite lists include suite IDs relative to its own ID. For example, if the test suite "core.suite1" contains the suites "core.suite2" , the suite ID in this suite is specified as "suite2" . The *Included Suites* list displays the IDs of suites that are explicitly included in this test suite. The *Available Suites* list displays the IDs of other test suites that may be included. To add a suite to this test suite, select it in the *Available Suites* list and click on *<< Add*. To remove a test suite from this test suite, select it in the *Included Suites* list and click on *Remove >>*. @ suite test IDs **Test IDs** The list displays the IDs of tests that are *explicitly* included in the test suite. Since the test suite may contain other tests suites, it may contain other tests as well. A test suite displays test IDs relative to its own ID. For example, if the test suite "core.suite" contains the tests "core.test1" and "core.linux.test2" , the test IDs in the suite are specified as "test1" and "linux.test2". @ suite test IDs control **Test IDs** **Test IDs** allows you to change the tests that are *explicitly* included in the test suite. Note that the suite may contain other tests, since it may include other test suites. A test suite lists test IDs relative to its own ID. For example, if the test suite "core.suite" contains the tests "core.test1" and "core.linux.test2" , the test IDs in the suite are specified as "test1" and "linux.test2". Only tests whose IDs begin with "core." may be included in the suite. The *Included Tests* list displays the IDs of tests that are explicitly included in the test suite. The *Available Tests* list displays the IDs of other tests that may be included. To add a test to the test suite, select it in the *Available Tests* list and click on *<< Add*. To remove a test from the test suite, select it in the *Included Tests* list and click on *Remove >>*. @ test class control **Test Class** The "test class" associated with a test indicates what kind of test it is. Select one of the available test classes. If %(program_name)s cannot find a test class that you think you have installed, you may need to set the 'QMTEST_CLASS_PATH' environment variable. This variable is like the 'PATH' environment variable, but contains a list of directories where %(program_name)s will look for test classes. %(classes)s @ test ID **Test ID** A test ID is a label that identifies a test. Test IDs are unique within a single test database, but are distinct from resource IDs and suite IDs. The test ID may be composed of lower-case letters, digits, hyphens, and underscores. You may optionally organize tests in a hierarchy using a period as the path separator. Paths specified this way define implicit test suites. For example, if your test database contains tests with these three IDs * core.test1 * core.test2 * test3 %(program_name)s recognizes an implicit test suite named "core" which contains the two tests "test1" and "test2". In addition, a test's prerequisites and resources are always specified relative to the test's path. So, for instance, "core.test2" would specify "test1" as a prerequisite, not "core.test1". This implies that a test cannot specify an resource or prerequisite in a different path (except in subpaths). For example, "core.test2" cannot specify "test3" as a prerequisite. ######################################################################## # Local Variables: # mode: text # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/share/qmtest/diagnostics/0000775000076400007640000000000011122067201017305 5ustar stefanstefanqmtest-2.4.1/share/qmtest/diagnostics/common.txt0000664000076400007640000001020111107032172021332 0ustar stefanstefan######################################################################## # # File: diagnostics.txt # Author: Alex Samuel # Date: 2001-03-08 # # Contents: # Common QM diagnostic message templates. # # Copyright (c) 2001, 2002 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## # Please keep diagnostics in alphabetical order by tag. @ address in use The address %(address)s is already in use by another process. Specify a different port for running the server. @ bad port number You must specify a numerical port number. @ browser error Could not start the web browser '%(browser_path)s'. @ conflicting options You may not specify both '--%(option1)s' and '--%(option2)s'. @ could not read file %(program_name)s could not read the file '%(path)s'. @ disabled account The account you specified is disabled. @ dom bad integer The value "%(value)s" is not an integer. The contents of an '' node must be an integer. @ dom wrong tag for field A '<%(wrong_tag)s>' element is not allowed for field %(name)s. Only a '<%(right_tag)s>' element may be used. @ empty set field value You must specify at least one value for the "%(field_title)s" field. @ empty text field value You must specify a value for the "%(field_title)s" field. @ ext arg name matches class var The extension class "%(class_name)s" has both a class variable and an argument with the name "%(argument_name)s". @ invalid descriptor syntax The extension descriptor is invalid. The invalid part of the descriptor is "%(start)s". A valid descriptor has the form "CLASS-NAME" or "CLASS-NAME(ARG1 = 'VAL1', ARG2 = 'VAL2', ...)". @ invalid enum key The string "%(key)s" is not a valid enumeral. Enumeral names must be composed of lower-case letters, digits, hyphens, and underscores. @ invalid enum value The value "%(value)s" is not allowed for field "%(field_title)s". The field may take the values %(values)s. @ invalid extension argument The argument "%(value)s" is not allowed for field "%(name)s". @ invalid integer field value The value of this field must be an integer. @ invalid login The user name or password you entered is invalid. Please log in again. @ invalid property The property '%(error)s' is invalid. Use the form 'NAME=VALUE' to specify properties. @ invalid set value The set value provided could not be parsed. The invalid part of the value is "%(start)s". A valid set value has the form "[ 'value1', 'value2', ... ]". @ missing command Specify a command. @ sendmail error Could not execute your mail transport agent, `%(sendmail_path)s'. @ server url %(program_name)s running at %(url)s @ session expired Your session has expired. Please log in again to start a new session. @ session invalid Your login session is invalid. Please log in again. @ session required To access the page you have requested, you must log in first. @ session wrong IP You have attempted to use a session from a network address different from that from which the session originated. A session may only be used from a single network address. Please log in again to start a new session. @ shutdown not allowed Only administrators may shut down the server. @ temp dir error An error occured while creating the temporary directory '%(dir_path)s'. Please check that your temporary directory is configured correctly. '%(exc_class)s: %(exc_arg)s' @ temp file error An error occured while creating the temporary file '%(file_name)s'. Please check that your temporary directory is configured correctly. '%(exc_class)s: %(exc_arg)s' @ unexpected extension argument "%(name)s" is not a valid argument to the "%(class_name)s" extension class. @ unrecognized command %(program_name)s does not recognize the command "%(command)s". @ xmlrpc exception An XML/RPC invocation caused an exception. %(exception)s @ xml parse error The XML parser encountered an error at line %(line)d, character %(character)d of the file %(file_name)s: '%(message)s' ######################################################################## # Local Variables: # mode: text # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/share/qmtest/diagnostics/common-help.txt0000664000076400007640000000240711107032172022271 0ustar stefanstefan######################################################################## # # File: common-help.txt # Author: Alex Samuel # Date: 2001-03-08 # # Contents: # Common QM help message templates. # # Copyright (c) 2001 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## # Please keep diagnostics in alphabetical order by tag. @ attachment form Using this form, you can upload a file from your computer as a file attachment. An attachment consists of the file's contents, plus the file name, the file's MIME type, and a short description. 1. In the **File** field, enter the path of the file you wish to upload, or click on "Browse" to browse the contents of your file system. 2. Specify the file's MIME type in the **Description** field. Select "Detect Automatically" to have %(program_name)s guess the MIME type automatically based on the file's name, or enter a valid MIME type in the edit control. 3. In the **Description** field, enter a short description of the file's contents. ######################################################################## # Local Variables: # mode: text # indent-tabs-mode: nil # fill-column: 72 # End: qmtest-2.4.1/share/qmtest/dtml/0000775000076400007640000000000011122067201015736 5ustar stefanstefanqmtest-2.4.1/share/qmtest/dtml/help.dtml0000664000076400007640000000222211110104351017541 0ustar stefanstefan

Help

Help

function popup_manual() { window.open("/manual/index.html", "manual", "resizable,toolbar,scrollbars"); } qmtest-2.4.1/share/qmtest/dtml/error.dtml0000664000076400007640000000130611110104357017752 0ustar stefanstefan

Error

qmtest-2.4.1/share/qmtest/dtml/attachment.dtml0000664000076400007640000001221411110104364020747 0ustar stefanstefan
" enctype="multipart/form-data"> ">

Upload file contents for field

File

Specify the file to upload.

MIME type

The MIME type can be inferred from the file name, or you may specify the MIME type explicitly.

 Detect Automatically
Specify:
Description

Enter a short description of the attachment.

function do_submit() { var parent_form = window.opener.document.form; var field = parent_form.; var summary_field = parent_form.; var description; var mime_type; var location; var file_name; var summary; // Get the name of the uploaded file. file_name = document.upload_form.file_data.value; // Keep the file name only; discard directories. file_name = file_name.replace(/.*\//, ""); file_name = file_name.replace(/.*\\/, ""); // Get the attachment description. description = document.upload_form.description.value; // If the description is ommitted (or whitespace only), use the file name. if(description.match(/^\s*$/) != null) description = file_name; // Get the on-server location of the uploaded attachment data. location = document.upload_form.location.value; // Get the MIME type. if(document.upload_form.detect_mime_type[0].checked) mime_type = ""; else mime_type = document.upload_form.mime_type.value; encoding = escape(description) + ";" + escape(mime_type) + ";" + escape(location) + ";" + escape(file_name) + ";" + escape(""); summary = description + " (" + file_name if(document.upload_form.detect_mime_type[1].checked) summary += "; " + mime_type; summary = summary + ")" window.opener.add_to_set(summary_field, field, summary, encoding); summary_field.value = summary; field.value = encoding; document.upload_form.submit(); } // This function is used to select the "Specify" radio button when // the user types into the MIME type text input. function set_no_detect_mime_type() { document.upload_form.detect_mime_type[1].checked = true; } qmtest-2.4.1/share/qmtest/dtml/test/0000775000076400007640000000000011122067201016715 5ustar stefanstefanqmtest-2.4.1/share/qmtest/dtml/test/new-suite.dtml0000664000076400007640000000417311107032170021524 0ustar stefanstefan

New Test Suite

" enctype="multipart/form-data"> class="field-error" class="field" >

Your issue submission contained errors. Please correct them and resubmit.

First, you must specify the ID for the new test suite.

Test Suite ID

The test suite ID identifies the suite.

"/>
qmtest-2.4.1/share/qmtest/dtml/test/dir.dtml0000664000076400007640000002412311107032171020360 0ustar stefanstefan

All tests have not yet been run. These results will be updated every few seconds.

Directory

">  
Result Summary for Result Summary
Outcome # of Tests % of Total # Unexpected % of Total
class="qmtest_unexpected" > class="qmtest_unexpected" >
Total 100 class="qmtest_unexpected" > class="qmtest_unexpected" >
Subdirectories of Subdirectories
Directory # Results Outcomes Expectations
 
" width="%">
 
" width="%">
 
Tests in Tests
">Test ">Outcome " >Expectation Details
  ')" > Details  
Suites in Suites
Suites
Resources in Resources
Resources
function run_dir() { location = ''; } function set_expectation(url) { window.open(url, "set_expectation", "dependent,height=200,width=640"); } qmtest-2.4.1/share/qmtest/dtml/test/navigation-bar.dtml0000664000076400007640000000774511107032170022515 0ustar stefanstefan
active_menu = null; function show_menu(event, id) { var base, menu, x, y; if (window.event) { base = window.event.toElement; } else { base = event.currentTarget; } x = get_left(base); y = get_bottom(base); menu = document.getElementById(id); menu.style.left = (new Number(x)).toString() + "px"; menu.style.top = (new Number(y)).toString() + "px"; if (active_menu) active_menu.style.visibility = "hidden"; menu.style.visibility = "visible"; active_menu = menu; } /* Called when the mouseout event is received by a menu. */ function hide_menu(event) { var target; /* Figure out to which element the mouse is moving. */ if (window.event) { target = window.event.toElement; } else { target = event.relatedTarget; } /* If that element is not a child of the menu, hide the menu. */ if (target && !is_parent_of(this, target)) this.style.visibility = "hidden"; } /* Called when an item on the menu bar is activated. The event is either a mouseover or onclick event. */ function hide_active_menu(event) { var target; /* If there is no active menu, there's nothing to hide. */ if (!active_menu) return; if (window.event) { target = window.event.toElement; } else { target = event.relatedTarget; } if (!is_parent_of(active_menu, target)) active_menu.style.visibility = "hidden"; } function load_context() { window.open("load-context", "load_context", "dependent,height=200,width=640"); } function load_results() { window.open("load-results", "load_results", "dependent,height=200,width=640"); } function load_expected_results() { window.open("load-expectations", "load_expectations", "dependent,height=200,width=640"); } document.getElementById("").onmouseout = hide_menu; qmtest-2.4.1/share/qmtest/dtml/test/show.dtml0000664000076400007640000001301511107032170020557 0ustar stefanstefan

New

Your issue submission contained errors. Please correct them and resubmit.

" enctype="multipart/form-data"> " /> " /> class="field-error" class="field" >
Class:
 
Arguments

 
onclick="location = ''" onclick="location = ''" />
function edit_item() { location = ''; } function delete_item() { } function run_test() { location = ''; } qmtest-2.4.1/share/qmtest/dtml/test/expectations.dtml0000664000076400007640000000267511107032171022320 0ustar stefanstefan

Expectations

 
qmtest-2.4.1/share/qmtest/dtml/test/context.dtml0000664000076400007640000000264311107032171021271 0ustar stefanstefan
" enctype="multipart/form-data">
Context Variables

Context variables provided to test classes.

qmtest-2.4.1/share/qmtest/dtml/test/result.dtml0000664000076400007640000000346311107032171021124 0ustar stefanstefan

Outcome Cause
Annotation Value
function run_test() { location = ''; } qmtest-2.4.1/share/qmtest/dtml/test/suite.dtml0000664000076400007640000001125711107032171020737 0ustar stefanstefan

Test Suite

" enctype="multipart/form-data" onsubmit="document.form.test_ids.value = encode_ids(document.form.incl_tests); document.form.suite_ids.value = encode_ids(document.form.incl_suites);"/> "/>
Test IDs

IDs of tests that are included in this suite.

None
Suite IDs

IDs of other suites that are included in this suite.

None
function move(src, dst) { if(src.selectedIndex == -1) return; var option = src[src.selectedIndex]; dst[dst.length] = new Option(option.text, option.value); src[src.selectedIndex] = null; } function encode_ids(select) { var result = ""; for(var i = 0; i < select.options.length; ++i) { if(i > 0) result += ","; result += select.options[i].value; } return result; }
function edit_suite() { location = ''; } function delete_suite() { } function run_suite() { location = ''; } qmtest-2.4.1/share/qmtest/dtml/test/results.dtml0000664000076400007640000001100511107032171021276 0ustar stefanstefan

All tests have not yet been run. These results will be updated every few seconds.

">  
Statistics
Outcome # of Tests % of Total # Unexpected % of Total
class="qmtest_unexpected" > class="qmtest_unexpected" >
Total 100 class="qmtest_unexpected" > class="qmtest_unexpected" >
">
Test Results
Test Outcome Expectation Details
')" > Details
function set_expectation(url) { window.open(url, "set_expectation", "dependent,height=200,width=640"); } qmtest-2.4.1/share/qmtest/dtml/test/load.dtml0000664000076400007640000000171111107032171020517 0ustar stefanstefan

qmtest-2.4.1/share/qmtest/dtml/test/new.dtml0000664000076400007640000000770711107032171020404 0ustar stefanstefan

" enctype="multipart/form-data"> class="field-error" class="field" > class="field-error" class="field" >

Your submission contained errors. Please correct them and resubmit.

Specify the name and class for the new .

Test Name

The test name identifies the test.

Resource Name

The resource name identifies the resource.

"/>
Class

The kind of to create.

Class:
qmtest-2.4.1/share/qmtest/dtml/test/set-expectation.dtml0000664000076400007640000000306311107032171022716 0ustar stefanstefan
"/>

Set expectation for

The expected outcome for .
 
qmtest-2.4.1/share/qmtest/dtml/user.dtml0000664000076400007640000000224311110104372017575 0ustar stefanstefan

User


  • Name:

  • Email Address: ">

qmtest-2.4.1/share/qmtest/dtml/field.dtml0000664000076400007640000000517611110104377017717 0ustar stefanstefan

Field

" enctype="multipart/form-data">
Field Type:
Default Value

The default value for this field.

 
Field Properties
 
Additional Properties

Properties provide hints about how this field should be used. Some properties are used internally by the field or by other parts of the system.

 
qmtest-2.4.1/share/qmtest/dtml/set.dtml0000664000076400007640000000445011110104412017407 0ustar stefanstefan

Add an element to the .

function add_item() { var item = document.form.item.value; var select = window.opener.document.form.; var contents = window.opener.document.form.; if(item != "") window.opener.add_to_set(select, contents, item, item); window.close(); return false; } qmtest-2.4.1/share/qmtest/dtml/add-enumeral.dtml0000664000076400007640000000326611110104417021163 0ustar stefanstefan

Add an Enumeral

Enumeral Name
function add_item() { var item = document.form.item.value; var select = window.opener.document.form.; var contents = window.opener.document.form.; if(item != "") window.opener.add_to_set(select, contents, item, item); window.close(); return false; } qmtest-2.4.1/share/qmtest/dtml/report/0000775000076400007640000000000011122067201017251 5ustar stefanstefanqmtest-2.4.1/share/qmtest/dtml/report/dir.dtml0000664000076400007640000001377611107032172020731 0ustar stefanstefan " method="get">

Directory

Column key: "/>
Row key: "/>
Number of rows: "/>
">
" width="%">
Subdirectories of Subdirectories
Directory Results
Tests in Tests
Test Outcomes
"> ">
qmtest-2.4.1/share/qmtest/dtml/report/show.dtml0000664000076400007640000001071211107032172021116 0ustar stefanstefan

Class:
" method="get">
Column key: "/>
Row key: "/>
Number of rows: "/>
"> ">
qmtest-2.4.1/share/qmtest/dtml/login_form.dtml0000664000076400007640000000161011110104423020744 0ustar stefanstefan
qmtest-2.4.1/share/qmtest/dtml/problems.dtml0000664000076400007640000000234311110104432020440 0ustar stefanstefan

Experiencing problems with QM Tools?

  • Consult the QM Tools Manual for information about installing, configuring, and using QMTest and QMTrack.

  • Contact CodeSourcery, LLC to obtain support for QM Tools.

  • If you think you've found a bug, or would like to request a change, enhancement, or new feature, send an email to qmtest@codesourcery.com.

qmtest-2.4.1/share/qmtest/dtml/exception.dtml0000664000076400007640000000255611110104444020624 0ustar stefanstefan

You Have Found a Bug in !

This page indicates that has encountered an internal error.

You can ">return to the main page.

function popup_qm_bug_system() { window.open("", "qm_bug_system"); }

Exception type:

Exception value:

Stack trace:

qmtest-2.4.1/share/qmtest/logo.bmp0000775000076400007640000005663211107032173016460 0ustar stefanstefanBM]zl(  ]  fehgfh.-1JJL #tsvfeh #tsv #ffh #JILtsvJILttvпmjj #JIL.-1..1ɶլ˙f̙gʢ}b\[ #JIL<;> #ɶϠq˙f̙g˙f˙f̙gϟq{tq #JIL #.-1ٳ˙g̙g̙g̙g̙g˙f˙f˙fΟp{tp #JILtsu #.-1Ҧz̙g̙g˙f˙f˙f̙g̙g˙g̙g˙fΟp{tq #/.1ttv #.-1ϟq̙g˙f˙f̙g˙f˙f˙f̙g˙f˙f̙g̙g̙g #.-1 # #լ̚g˙f̙g˙f̙g̙g̙g˙f˙f̙g˙g̙g˙f˙g̚g #/.1! # #۹̙g˙f̙g˙f˙f˙f̚g̙g̙g˙f̙g˙f̚g̙g˙f̙g˙f # #<;? #.-0̙g˙f̙g˙g̙g˙f̙g˙f̙g˙f˙f̙g˙f̚g̙g˙g˙f˙f̙g.-1 #JIL # #XWZ # #Ҧy̙g̙g˙f˙f̙g˙f̚g̙g̙g˙g˙f˙f˙f̙g̙g˙f̙g˙f̙g̙g.-0 #..1 # # #tsv.-1 # #tsv # # #<;?.-1 # # # # #! #XWZ # # #! #.-1 # #XWZffh # # #..1 # "XWZ # #feg<;? "! #..1 # # # # # # # # # # " #JIL #.-1п˙g̙g˙f˙f̚g̙g̙g˙f˙g̙g˙g˙f˙f̙g˙g˙f̚g˙g̙g̚g˙f̙g.-1 # # # # # # #<;? # # # #JIL # # # # "XWZ # # #! # # #<;? # # #XWZ # # # #JIL # # # # #KJL # #ffh # #XXZ.-1 # " # # # # # # # #tsv # # # # # # # #tsv̙֭g˙f̙g̚g̙g̙g̙g˙f̙g˙g̙g˙f̚g˙f˙f̙g˙f̙g̙g˙f˙f˙g̙gROO #tsv # # #.-1utvfeh " # # # # #<;? #<;?XWZ # #<;? # #feg # # # #ttvtsv # # # # " " # #ttvXWZ # #tsv # # # # # # # # # #˙f˙f˙f̙g˙f̙g˙f˙f˙f̚g˙f˙f˙f˙f˙f˙f̙g˙f̙g̙g˙f̚g˙f̙g̚gʢ|SOO #< # # # # # #XWZ۹̙g˙f˙f̙g˙f̙g˙f˙f˙g̙gҦy # #tsuXWZ{xxɬٳٳسͩ~ #.-1 # # " # "XXZ # #XWZ # # # #XXZ # #= # #! # # #! # # # # " # # #.-0feh #XXZXWZ #XWZ # #سĮ˙f̙g˙g˙f˙f˙f̙g˙f̙g˙f̙g̙gΟp #JIL # # #tsvgfhXWZ # # #ttvXWZttvXWZXWZXXZfehtsvXWZXWZtsvXWZJIL # #ϟq׭̙g̙g̙g̙g˙f˙f̙g˙g˙g̙g̚g̙gĮ..1< qmtest-2.4.1/share/qmtest/dtds/class-directory.dtd0000664000076400007640000000106711107032173021547 0ustar stefanstefan qmtest-2.4.1/share/qmtest/dtds/result.dtd0000664000076400007640000000162011107032173017751 0ustar stefanstefan qmtest-2.4.1/share/qmtest/xml/0000775000076400007640000000000011122067201015576 5ustar stefanstefanqmtest-2.4.1/share/qmtest/xml/report.xslt0000664000076400007640000002511511107032172020033 0ustar stefanstefan <xsl:value-of select="$title" />

Summary

Subdirectories

Subdirectory

Tests

Resources

Results for subdirectory <xsl:value-of select="$title" />

Directory

Subdirectories

Subdirectory

Tests

Resources

Detailed results for test suite <xsl:value-of select="$title" />

tests

passes

failures

pass xpass xfail fail untested pass fail untested
qmtest-2.4.1/share/qmtest/xml/fields.mod0000664000076400007640000000175011107032172017552 0ustar stefanstefan qmtest-2.4.1/share/logo.bmp0000775000076400007640000005663211107032173015143 0ustar stefanstefanBM]zl(  ]  fehgfh.-1JJL #tsvfeh #tsv #ffh #JILtsvJILttvпmjj #JIL.-1..1ɶլ˙f̙gʢ}b\[ #JIL<;> #ɶϠq˙f̙g˙f˙f̙gϟq{tq #JIL #.-1ٳ˙g̙g̙g̙g̙g˙f˙f˙fΟp{tp #JILtsu #.-1Ҧz̙g̙g˙f˙f˙f̙g̙g˙g̙g˙fΟp{tq #/.1ttv #.-1ϟq̙g˙f˙f̙g˙f˙f˙f̙g˙f˙f̙g̙g̙g #.-1 # #լ̚g˙f̙g˙f̙g̙g̙g˙f˙f̙g˙g̙g˙f˙g̚g #/.1! # #۹̙g˙f̙g˙f˙f˙f̚g̙g̙g˙f̙g˙f̚g̙g˙f̙g˙f # #<;? #.-0̙g˙f̙g˙g̙g˙f̙g˙f̙g˙f˙f̙g˙f̚g̙g˙g˙f˙f̙g.-1 #JIL # #XWZ # #Ҧy̙g̙g˙f˙f̙g˙f̚g̙g̙g˙g˙f˙f˙f̙g̙g˙f̙g˙f̙g̙g.-0 #..1 # # #tsv.-1 # #tsv # # #<;?.-1 # # # # #! #XWZ # # #! #.-1 # #XWZffh # # #..1 # "XWZ # #feg<;? "! #..1 # # # # # # # # # # " #JIL #.-1п˙g̙g˙f˙f̚g̙g̙g˙f˙g̙g˙g˙f˙f̙g˙g˙f̚g˙g̙g̚g˙f̙g.-1 # # # # # # #<;? # # # #JIL # # # # "XWZ # # #! # # #<;? # # #XWZ # # # #JIL # # # # #KJL # #ffh # #XXZ.-1 # " # # # # # # # #tsv # # # # # # # #tsv̙֭g˙f̙g̚g̙g̙g̙g˙f̙g˙g̙g˙f̚g˙f˙f̙g˙f̙g̙g˙f˙f˙g̙gROO #tsv # # #.-1utvfeh " # # # # #<;? #<;?XWZ # #<;? # #feg # # # #ttvtsv # # # # " " # #ttvXWZ # #tsv # # # # # # # # # #˙f˙f˙f̙g˙f̙g˙f˙f˙f̚g˙f˙f˙f˙f˙f˙f̙g˙f̙g̙g˙f̚g˙f̙g̚gʢ|SOO #< # # # # # #XWZ۹̙g˙f˙f̙g˙f̙g˙f˙f˙g̙gҦy # #tsuXWZ{xxɬٳٳسͩ~ #.-1 # # " # "XXZ # #XWZ # # # #XXZ # #= # #! # # #! # # # # " # # #.-0feh #XXZXWZ #XWZ # #سĮ˙f̙g˙g˙f˙f˙f̙g˙f̙g˙f̙g̙gΟp #JIL # # #tsvgfhXWZ # # #ttvXWZttvXWZXWZXXZfehtsvXWZXWZtsvXWZJIL # #ϟq׭̙g̙g̙g̙g˙f˙f̙g˙g˙g̙g̚g̙gĮ..1<>k,ՉC%[ $S|s(VBoPm;f,fkS[LH\)T0E_%I1LP/)ֿ$(P!bNzǫpc=rxUauuwuu8X/X9qmtest-2.4.1/share/doc/0000775000076400007640000000000011122067201014226 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/0000775000076400007640000000000011122067201015543 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/html/0000775000076400007640000000000011122067201016507 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/html/manual/0000775000076400007640000000000011122067201017764 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_stream-pysrc.html0000664000076400007640000055256511122067162030056 0ustar stefanstefan qm.test.classes.dejagnu_stream
Package qm :: Package test :: Package classes :: Module dejagnu_stream
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.dejagnu_stream

  1  ######################################################################## 
  2  # 
  3  # File:   dejagnu_stream.py 
  4  # Author: Mark Mitchell 
  5  # Date:   04/30/2003 
  6  # 
  7  # Contents: 
  8  #   DejaGNUStream 
  9  # 
 10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import cgi 
 21  from   dejagnu_test import DejaGNUTest 
 22  import qm.fields 
 23  from   qm.test.file_result_stream import FileResultStream 
 24  from   qm.test.result import Result 
 25  from   qm.test.file_result_reader import FileResultReader 
 26  import re 
 27   
 28  ######################################################################## 
 29  # Classes 
 30  ######################################################################## 
 31   
32 -class DejaGNUStream(FileResultStream):
33 """A 'DejaGNUStream' formats its output like DejaGNU.""" 34 35 arguments = [ 36 qm.fields.BooleanField( 37 name = "show_expected_outcomes", 38 title = "Show Expected Outcomes", 39 description = """True if expected outcomes should be displayed. 40 41 By default, only information about unexpected outcomes is 42 displayed.""", 43 default_value = "false" 44 ) 45 ] 46 47 __summary_outcomes = [ 48 DejaGNUTest.PASS, 49 DejaGNUTest.FAIL, 50 DejaGNUTest.KFAIL, 51 DejaGNUTest.KPASS, 52 DejaGNUTest.XPASS, 53 DejaGNUTest.XFAIL, 54 DejaGNUTest.UNRESOLVED, 55 DejaGNUTest.UNTESTED, 56 DejaGNUTest.UNSUPPORTED 57 ] 58 """The outcomes for which summary output should be produced.""" 59 60 __outcome_descs = { 61 DejaGNUTest.PASS: "expected passes", 62 DejaGNUTest.FAIL: "unexpected failures", 63 DejaGNUTest.KPASS: "unexpected successes", 64 DejaGNUTest.KFAIL: "expected failures", 65 DejaGNUTest.XPASS: "unexpected successes", 66 DejaGNUTest.XFAIL: "expected failures", 67 DejaGNUTest.UNRESOLVED: "unresolved testcases", 68 DejaGNUTest.UNTESTED: "untested testcases", 69 DejaGNUTest.UNSUPPORTED: "unsupported tests", 70 } 71 """A map from DejaGNU outcomes to descriptions. 72 73 See 'init_testcounts' in the DejaGNU distribution for the code 74 emulated by this table.""" 75 76 __expected_outcomes = ( 77 DejaGNUTest.PASS, 78 DejaGNUTest.KFAIL, 79 DejaGNUTest.XFAIL, 80 DejaGNUTest.UNRESOLVED, 81 DejaGNUTest.UNSUPPORTED, 82 DejaGNUTest.UNTESTED 83 ) 84 """The DejaGNU outcomes that are considered "expected" results. 85 86 DejaGNU results with these outcomes are not displayed unless 87 'show_expected_outcomes' is true.""" 88
89 - def __init__(self, arguments = None, **args):
90 91 super(DejaGNUStream, self).__init__(arguments, **args) 92 self.__outcomes = {} 93 for o in DejaGNUTest.dejagnu_outcomes: 94 self.__outcomes[o] = 0
95 96
97 - def WriteResult(self, result):
98 99 # Get the DejaGNU annotations in sorted order. 100 keys = filter(lambda k: k.startswith(DejaGNUTest.RESULT_PREFIX), 101 result.keys()) 102 keys.sort(lambda k1, k2: cmp(int(k1[len(DejaGNUTest.RESULT_PREFIX):]), 103 int(k2[len(DejaGNUTest.RESULT_PREFIX):]))) 104 has_error = 0 105 for k in keys: 106 r = result[k] 107 outcome = r[:r.find(":")] 108 if (self.show_expected_outcomes == "true" 109 or outcome not in self.__expected_outcomes): 110 self.file.write(r + "\n") 111 # Keep track of the outcomes. 112 self.__outcomes[outcome] += 1 113 if outcome == DejaGNUTest.ERROR: 114 has_error = 1 115 116 # If something went wrong running the test, emit an ERROR 117 # message even if DejaGNU would not have. These cases usually 118 # indicate problems with the DejaGNU test itself. 119 if not has_error and result.GetOutcome () == result.ERROR: 120 self.file.write("ERROR: %s (%s)\n" 121 % (result.GetId(), result.GetCause())) 122 self.__outcomes[DejaGNUTest.ERROR] += 1
123 124
125 - def Summarize(self):
126 127 self.file.write("\n\t\t=== Summary ===\n\n") 128 # This function emulates log_summary from the DejaGNU 129 # distribution. 130 for o in self.__summary_outcomes: 131 if self.__outcomes[o]: 132 desc = "# of %s" % self.__outcome_descs[o] 133 self.file.write(desc) 134 if len(desc) < 24: 135 self.file.write("\t") 136 self.file.write("\t%d\n" % self.__outcomes[o])
137 138 139
140 -class DejaGNUReader(FileResultReader):
141 """A 'DejaGNUReader' reads a DejaGNU log file. 142 143 The DejaGNU log file may then be processed by QMTest. For 144 example, QMTest may generate results in an alternative format, or 145 display them in the QMTest GUI. Therefore, this reader may be 146 used to obtain the benefits of QMTest's reporting characteristics, 147 when using a legacy DejaGNU testsuite. 148 149 Unfortunately, DejaGNU log files are relativley unstructured. 150 Therefore, this result reader uses heuristics that may not always 151 be 100% robust. Therefore, for optimal behavior, DejaGNU 152 testsuites should be converted to QMTest testsuites.""" 153 154 arguments = [ 155 qm.fields.BooleanField( 156 name = "is_combined", 157 title = "Combined Format?", 158 description=\ 159 """True if multiple results for the same test should be combined. 160 161 DejaGNU will sometimes print multiple results for the same 162 test. For example, when testing a compiler, DejaGNU may 163 issue one result indicating whether or not a file was 164 successfully compiled and another result indicating 165 whether or not the file was successfully executed. When 166 using the combined format, these two results will be treated as 167 subparts of a single test. When not using the combined 168 format, these results will be treated as separate 169 tests. 170 171 The combined format is the default. However, if you want 172 to see statistics that precisely match DejaGNU, you should 173 not use the combined format.""", 174 default_value="true", 175 ), 176 qm.fields.BooleanField( 177 name = "expectations", 178 title = "GenerateExpectations?", 179 description=\ 180 """True if expected (not actual) results should be generated. 181 182 In this mode, the actual results will be ignored. 183 Instead, a results file indicated expected failures as 184 actual failures will be generated.""", 185 default_value="false", 186 ), 187 ] 188 189 __id_regexp = re.compile("^[^:]*:[\\s]*(?P<id>[^\\s]*)") 190 """A regular expression for determining test names. 191 192 When applied to an outcome line from DejaGNU, this regular 193 expression's 'id' field gives the name of the test, in the 194 combined mode.""" 195 196 __cause_regexp = re.compile("\\((?P<cause>.*)\\)\\s*$") 197 """A regular expression for determining failure causes. 198 199 When applied to an outcome line from DejaGNU, this regular 200 expression's 'cause' field gives the cause of the failure.""" 201
202 - def __init__(self, arguments = None, **args):
203 204 # Initialize the base class. 205 super(DejaGNUReader, self).__init__(arguments, **args) 206 # DejaGNU files start with "Test Run". 207 if self.file.read(len("Test Run")) != "Test Run": 208 raise FileResultReader.InvalidFile, \ 209 "file is not a DejaGNU result stream" 210 self.file.seek(0) 211 if self.__UseCombinedMode(): 212 test_id, dejagnu_outcome, cause = self.__NextOutcome() 213 if test_id: 214 self.__next_result = Result(Result.TEST, test_id) 215 self.__UpdateResult(self.__next_result, 216 dejagnu_outcome, 217 cause)
218 219
220 - def GetResult(self):
221 222 if self.__UseCombinedMode(): 223 result = self.__next_result 224 if not result: 225 return None 226 self.__next_result = None 227 else: 228 result = None 229 while True: 230 test_id, dejagnu_outcome, cause = self.__NextOutcome() 231 # If there are no more results, stop. 232 if not test_id: 233 break 234 if self.__UseCombinedMode() and test_id != result.GetId(): 235 self.__next_result = Result(Result.TEST, test_id) 236 self.__UpdateResult(self.__next_result, 237 dejagnu_outcome, 238 cause) 239 break 240 elif not self.__UseCombinedMode(): 241 result = Result(Result.TEST, test_id) 242 self.__UpdateResult(result, dejagnu_outcome, cause) 243 if not self.__UseCombinedMode(): 244 break 245 return result
246 247
248 - def __NextOutcome(self):
249 """The next DejaGNU outcome in the file. 250 251 returns -- A triplet ('test_id', 'outcome', 'cause'). The 252 'test_id' is the name of the test. The 'outcome' is the 253 DejaGNU outcome (one of the 'DejaGNUTest.dejagnu_outcomes'). 254 The 'cause' is a string giving the cause (if known) of 255 failure, if the test did not pass.""" 256 257 # Assume that there are no more results in the file. 258 dejagnu_outcome = None 259 # Scan ahead until we find a line that gives data about the 260 # next result. 261 while self.file: 262 # Read the next line of the file. 263 line = self.file.next() 264 # Each test result is printed on a line by itself, 265 # beginning with the DejaGNU outcome. For example: 266 # PASS: g++.dg/compat/eh/template1 cp_compat_y_tst.o compile 267 dejagnu_outcome = None 268 for o in DejaGNUTest.dejagnu_outcomes: 269 # Ignore WARNING and ERROR; those are not really test 270 # results. 271 if (o not in (DejaGNUTest.WARNING, 272 DejaGNUTest.ERROR) 273 and line.startswith(o)): 274 o_len = len(o) 275 if line[o_len:o_len + 2] == ": ": 276 dejagnu_outcome = o 277 break 278 if dejagnu_outcome: 279 break 280 # If we could not find any more result lines, then we have 281 # read all of the results in the file. 282 if not dejagnu_outcome: 283 return None, None, None 284 # Extract the name of the test. 285 if self.__UseCombinedMode(): 286 match = self.__id_regexp.search(line) 287 test_id = match.group("id") 288 else: 289 test_id = line[len(dejagnu_outcome) + 2:].strip() 290 # Extract the cause of faiulre. 291 cause = None 292 if "execution test" in line: 293 cause = "Compiled program behaved incorrectly." 294 elif dejagnu_outcome == DejaGNUTest.UNSUPPORTED: 295 cause = "Test is not applicable on this platform." 296 elif self.__UseCombinedMode(): 297 match = self.__cause_regexp.search(line) 298 if match: 299 cause = match.group("cause").capitalize() 300 if cause and cause[-1] != ".": 301 cause += "." 302 else: 303 cause = "" 304 return test_id, dejagnu_outcome, cause
305 306
307 - def __UpdateResult(self, result, dejagnu_outcome, cause):
308 """Update 'result' as indicated. 309 310 'result' -- A 'Result', which may contain information from 311 previous DejaGNU tests, in the combined mode. 312 313 'dejagnu_outcome' -- The DejaGNU outcome (one of the 314 'DejaGNUTest.dejagnu_outcomes') that applies to this 315 'result'. 316 317 'cause' -- The cause of failure, if known. 318 319 The 'result' is modified to reflect the new outcome and 320 cause. Results can only get worse, in the sense that if 321 reuslt has an outcome of 'Result.FAIL' upon entry to this 322 return, it will never have an outcome of 'Result.PASS' upon 323 return.""" 324 325 # Translate the DejaGNU outcome into a QMTest outcome. 326 if self.__GenerateExpectations(): 327 if dejagnu_outcome in (DejaGNUTest.KFAIL, 328 DejaGNUTest.KPASS, 329 DejaGNUTest.XFAIL, 330 DejaGNUTest.XPASS): 331 qmtest_outcome = Result.FAIL 332 elif dejagnu_outcome in (DejaGNUTest.UNSUPPORTED, 333 DejaGNUTest.UNRESOLVED): 334 qmtest_outcome = Result.UNTESTED 335 else: 336 qmtest_outcome = Result.PASS 337 else: 338 qmtest_outcome = DejaGNUTest.outcome_map[dejagnu_outcome] 339 # Update the QMTest result for this test, based on the 340 # DejaGNU result. 341 if qmtest_outcome == Result.ERROR: 342 result.SetOutcome(Result.ERROR) 343 elif (qmtest_outcome == Result.UNTESTED 344 and result.GetOutcome() != Result.ERROR): 345 result.SetOutcome(Result.UNTESTED) 346 elif (qmtest_outcome == Result.FAIL 347 and result.GetOutcome() not in (Result.ERROR, 348 Result.UNTESTED)): 349 result.SetOutcome(Result.FAIL) 350 if qmtest_outcome != Result.PASS and cause: 351 old_cause = result.GetCause() 352 if old_cause and cause in old_cause: 353 # Don't repeat the same cause multiple times. 354 pass 355 else: 356 if old_cause: 357 old_cause += " " 358 old_cause += cgi.escape(cause) 359 result.SetCause(old_cause)
360 361
362 - def __UseCombinedMode(self):
363 """Returns true in the combined mode. 364 365 returns -- True iff results should be read in the combined 366 mode.""" 367 368 return self.is_combined == "true"
369 370
371 - def __GenerateExpectations(self):
372 """Returns true if expected results should be generated. 373 374 returns -- True iff the results generated should reflect 375 expectations, rather than actual results.""" 376 377 return self.expectations == "true"
378 379 ######################################################################## 380 # Miscellaneous 381 ######################################################################## 382 383 __all__ = ["DejaGNUStream", "DejaGNUReader"] 384

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.thread_target.LocalThread-class.html0000664000076400007640000003213611122067147032017 0ustar stefanstefan qm.test.classes.thread_target.LocalThread
Package qm :: Package test :: Package classes :: Module thread_target :: Class LocalThread
[hide private]
[frames] | no frames]

Class LocalThread

source code

          object --+            
                   |            
  threading._Verbose --+        
                       |        
        threading.Thread --+    
                           |    
command_thread.CommandThread --+
                               |
                              LocalThread

A 'LocalThread' executes commands locally.

Instance Methods [hide private]
 
__init__(self, target)
Construct a new 'CommandThread'.
source code
 
_RunTest(self, descriptor, context)
Run the test given by 'descriptor'.
source code
 
GetTemporaryDirectory(self)
Return the path to the temporary directory for this thread.
source code

Inherited from command_thread.CommandThread: GetTarget, RunTest, Stop, run

Inherited from command_thread.CommandThread (private): _Stop, _Trace

Inherited from threading.Thread: __repr__, getName, isAlive, isDaemon, join, setDaemon, setName, start

Inherited from threading.Thread (private): _set_daemon

Inherited from threading._Verbose (private): _note

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, target)
(Constructor)

source code 

Construct a new 'CommandThread'.

'target' -- The 'Target' that owns this thread.

Overrides: object.__init__
(inherited documentation)

_RunTest(self, descriptor, context)

source code 

Run the test given by 'descriptor'.

'descriptor' -- The name of the test to be run.

'context' -- The 'Context' in which to run the test.

Overrides: command_thread.CommandThread._RunTest

GetTemporaryDirectory(self)

source code 

Return the path to the temporary directory for this thread.

returns -- The path to the temporary directory associated with this thread.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.sql_result_stream-pysrc.html0000664000076400007640000043350111122067153030622 0ustar stefanstefan qm.test.classes.sql_result_stream
Package qm :: Package test :: Package classes :: Module sql_result_stream
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.sql_result_stream

  1  ######################################################################## 
  2  # 
  3  # File:   sql_result_stream.py 
  4  # Author: Nathaniel Smith <njs@codesourcery.com> 
  5  # Date:   2003-06-13 
  6  # 
  7  # Contents: 
  8  #   SQLResultStream, SQLResultSource 
  9  # 
 10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm.fields 
 21  from qm.extension          import Extension 
 22  from qm.test.result_stream import ResultStream 
 23  from qm.test.result_reader import ResultReader 
 24  from qm.db                 import quote_string, Connection 
 25  from qm.test.result        import Result 
 26   
 27  ######################################################################## 
 28  # Classes 
 29  ######################################################################## 
 30   
31 -class _SQLConnected(Extension):
32 """Mixin class for classes that need a database connection.""" 33 34 arguments = [ 35 qm.fields.TextField( 36 name = "db_name", 37 title = "Database name", 38 description = "The PostgreSQL database to connect to.", 39 verbatim = "true", 40 default_value = ""), 41 qm.fields.TextField( 42 name = "db_module", 43 title = "Database module", 44 description = "The DB 2.0 module to use.", 45 verbatim = "true", 46 default_value = "pgdb"), 47 qm.fields.PythonField( 48 name = "connection"), 49 ] 50
51 - def __init__(self, arguments = None, **args):
52 53 if arguments: args.update(arguments) 54 super(_SQLConnected, self).__init__(**args) 55 56 if not self.connection: 57 self.connection = Connection(self.db_module, 58 database=self.db_name)
59 60 61
62 -class SQLResultStream(ResultStream, _SQLConnected):
63 """A 'SQLResultStream' writes results out to an SQL database. 64 65 This class currently supports PostgreSQL only.""" 66 67
68 - def __init__(self, arguments = None, **args):
69 70 super(SQLResultStream, self).__init__(arguments, **args) 71 72 run_id_cursor = self.connection.execute(""" 73 SELECT nextval('run_id_seq'); 74 """) 75 (self._run_id,) = run_id_cursor.fetchone() 76 77 self.connection.execute(""" 78 INSERT INTO runs (run_id) VALUES (%i) 79 """ % (self._run_id,))
80 81
82 - def WriteAnnotation(self, key, value):
83 84 self.connection.execute(""" 85 INSERT INTO run_annotations (run_id, key, value) 86 VALUES (%i, %s, %s) 87 """ % (self._run_id, 88 quote_string(key), 89 quote_string(value)))
90 91
92 - def WriteResult(self, result):
93 94 self.connection.execute(""" 95 INSERT INTO results (run_id, result_id, kind, outcome) 96 VALUES (%i, %s, %s, %s) 97 """ % (self._run_id, 98 quote_string(result.GetId()), 99 quote_string(result.GetKind()), 100 quote_string(result.GetOutcome()))) 101 102 for key, value in result.items(): 103 self.connection.execute(""" 104 INSERT INTO result_annotations (run_id, 105 result_id, 106 result_kind, 107 key, 108 value) 109 VALUES (%i, %s, %s, %s, %s) 110 """ % (self._run_id, 111 quote_string(result.GetId()), 112 quote_string(result.GetKind()), 113 quote_string(key), 114 quote_string(value)))
115 116
117 - def Summarize(self):
118 119 self.connection.commit()
120 121 122
123 -class _Buffer:
124 """A little buffering iterator with one-element rewind.""" 125
126 - def __init__(self, size, get_more):
127 """Create a '_Buffer'. 128 129 'size' -- the number of items to hold in the buffer at a time. 130 131 'get_more' -- a function taking a number as its sole argument; 132 should return a list of that many new items (or as 133 many items are left, whichever is less). 134 """ 135 136 self.size = size 137 self.get_more = get_more 138 self.buffer = get_more(size) 139 self.idx = 0 140 # Needed for rewinding over buffer refills: 141 self.last = None
142 143
144 - def next(self):
145 """Returns the next item, refilling the buffer if necessary.""" 146 147 idx = self.idx 148 if idx == len(self.buffer): 149 self.buffer = self.get_more(self.size) 150 self.idx = 0 151 idx = 0 152 if not self.buffer: 153 raise StopIteration 154 self.idx += 1 155 self.last = self.buffer[idx] 156 return self.buffer[idx]
157 158
159 - def rewind(self):
160 161 if self.idx == 0: 162 self.buffer.insert(0, self.last) 163 else: 164 self.idx -= 1
165 166
167 - def __iter__(self):
168 169 return self
170 171 172
173 -class SQLResultReader(ResultReader, _SQLConnected):
174 """A 'SQLResultReader' reads result in from an SQL database. 175 176 This class currently supports PostgreSQL only.""" 177 178 arguments = [ 179 qm.fields.IntegerField( 180 name = "run_id", 181 title = "Run ID", 182 ), 183 ] 184
185 - def __init__(self, arguments = None, **args):
186 187 super(SQLResultReader, self).__init__(arguments, **args) 188 189 self._batch_size = 1000 190 191 self._LoadAnnotations() 192 self._SetupResultCursors()
193 194
195 - def _LoadAnnotations(self):
196 197 cursor = self.connection.execute(""" 198 SELECT key, value FROM run_annotations 199 WHERE run_id = %i 200 """ % (self.run_id)) 201 202 self._annotations = dict(iter(cursor.fetchone, None))
203 204
205 - def GetAnnotations(self):
206 207 return self._annotations
208 209
210 - def _SetupResultCursors(self):
211 212 # Set up our two result cursors. 213 self.connection.execute(""" 214 DECLARE results_c CURSOR FOR 215 SELECT result_id, kind, outcome FROM results 216 WHERE run_id = %i 217 ORDER BY result_id, kind 218 """ % (self.run_id,)) 219 self.connection.execute(""" 220 DECLARE annote_c CURSOR FOR 221 SELECT result_id, result_kind, key, value 222 FROM result_annotations WHERE run_id = %i 223 ORDER BY result_id, result_kind 224 """ % (self.run_id,)) 225 226 def get_more_results(num): 227 return self.connection.execute(""" 228 FETCH FORWARD %i FROM results_c 229 """ % (num,)).fetchall()
230 def get_more_annotations(num): 231 return self.connection.execute(""" 232 FETCH FORWARD %i FROM annote_c 233 """ % (num,)).fetchall()
234 235 self._r_buffer = _Buffer(self._batch_size, get_more_results) 236 self._a_buffer = _Buffer(self._batch_size, get_more_annotations) 237 238
239 - def GetResult(self):
240 241 try: 242 id, kind, outcome = self._r_buffer.next() 243 except StopIteration: 244 return None 245 annotations = {} 246 for result_id, result_kind, key, value in self._a_buffer: 247 if (result_id, result_kind) != (id, kind): 248 self._a_buffer.rewind() 249 break 250 annotations[key] = value 251 return Result(kind, id, outcome, annotations)
252 253 ######################################################################## 254 # Local Variables: 255 # mode: python 256 # indent-tabs-mode: nil 257 # fill-column: 72 258 # End: 259

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.attachment.AttachmentStore-class.html0000664000076400007640000003666311122067145027652 0ustar stefanstefan qm.attachment.AttachmentStore
Package qm :: Module attachment :: Class AttachmentStore
[hide private]
[frames] | no frames]

Class AttachmentStore

source code

object --+
         |
        AttachmentStore
Known Subclasses:

Interface for classes which store attachment data.

An attachment store stores the raw data for an attachment. The store is not responsible for storing auxiliary information, including the attachment's description, file name, or MIME type.

Users of an 'AttachmentStore' reference attachment data by a *location*, which is stored with the attachment.

Please note that the 'AttachmentStore' interface provides methods for retrieving attachment data only; not for storing it. The interface for storing may be defined in any way by implementations.

Instance Methods [hide private]
 
GetData(self, location)
Return the data for an attachment.
source code
 
GetDataFile(self, location)
Return the path to a file containing the data for 'attachment'.
source code
 
GetSize(self, location)
Return the size of the data for an attachment.
source code
 
HandleDownloadRequest(self, request)
Handle a web request to download attachment data.
source code
 
Store(self, attachment, location)
Add an attachment to the store.
source code

Inherited from object: __delattr__, __getattribute__, __hash__, __init__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

GetData(self, location)

source code 

Return the data for an attachment.

returns -- A string containing the attachment data.

GetDataFile(self, location)

source code 

Return the path to a file containing the data for 'attachment'.

returns -- A file system path.

The file is read-only, and may be a temporary file. The caller should not modify the file in any way.

GetSize(self, location)

source code 

Return the size of the data for an attachment.

returns -- The length of the attachment data, in bytes.

This method may be overridden by derived classes.

HandleDownloadRequest(self, request)

source code 

Handle a web request to download attachment data.

'request' -- A 'WebRequest' object. The location of the attachment data is stored in the 'location' property, and the MIME type in the 'mime_type' property.

returns -- A pair '(mime_type, data)' where 'mime_type' is the MIME type stored in the request and 'data' is the contents of the attachment.

Store(self, attachment, location)

source code 

Add an attachment to the store.

'attachment' -- The 'Attachment' to store.

'location' -- The location in which to store the 'attachment'.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate-module.html0000664000076400007640000000214311122067144030435 0ustar stefanstefan DocumentTemplate

Module DocumentTemplate


Variables

__doc__

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/module-tree.html0000664000076400007640000004715711122067144023120 0ustar stefanstefan Module Hierarchy
 
[hide private]
[frames] | no frames]
[ Module Hierarchy | Class Hierarchy ]

Module Hierarchy

././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.mount_database.MountDatabase.MountedSuite-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.mount_database.MountDatabase.MountedSuite-0000664000076400007640000004504511122067147033173 0ustar stefanstefan qm.test.classes.mount_database.MountDatabase.MountedSuite
Package qm :: Package test :: Package classes :: Module mount_database :: Class MountDatabase :: Class MountedSuite
[hide private]
[frames] | no frames]

Class MountedSuite

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
            suite.Suite --+
                          |
                         MountDatabase.MountedSuite

A 'MountedSuite' is a suite from a mounted database.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, suite_id, joiner, suite)
Construct a new 'Runnable'.
source code
 
IsImplicit(self)
Return true if this is an implicit test suite.
source code
 
GetTestIds(self)
Return the tests contained in this suite.
source code
 
GetSuiteIds(self)
Return the suites contained in this suite.
source code

Inherited from suite.Suite: GetAllTestAndSuiteIds, GetDatabase, GetId

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from suite.Suite: EXTRA_DATABASE, EXTRA_ID, arguments, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, suite_id, joiner, suite)
(Constructor)

source code 

Construct a new 'Runnable'.

'arguments' -- As for 'Extension.__init__'.

'args' -- As for 'Extension.__init__'.

Overrides: object.__init__
(inherited documentation)

IsImplicit(self)

source code 

Return true if this is an implicit test suite.

Implicit test suites cannot be edited.

Overrides: suite.Suite.IsImplicit
(inherited documentation)

GetTestIds(self)

source code 

Return the tests contained in this suite.

returns -- A sequence of labels corresponding to the tests contained in this suite. Tests that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetTestIds
(inherited documentation)

GetSuiteIds(self)

source code 

Return the suites contained in this suite.

returns -- A sequence of labels corresponding to the suites contained in this suite. Suites that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetSuiteIds
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.report-module.html0000664000076400007640000000211611122067144025633 0ustar stefanstefan report

Module report


Classes

ReportGenerator

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.config-module.html0000664000076400007640000000251611122067144024613 0ustar stefanstefan config

Module config


Variables

data_dir
doc_dir
extension_path
version

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/string._multimap-class.html0000664000076400007640000001335311122067151025262 0ustar stefanstefan string._multimap
string :: _multimap :: Class _multimap
[hide private]
[frames] | no frames]

Class _multimap

source code

Helper class for combining multiple mappings.

Used by .{safe_,}substitute() to combine the mapping and keyword arguments.

Instance Methods [hide private]
 
__getitem__(self, key) source code
 
__init__(self, primary, secondary) source code
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.simulator.Simulator-class.html0000664000076400007640000004112311122067147031012 0ustar stefanstefan qm.test.classes.simulator.Simulator
Package qm :: Package test :: Package classes :: Module simulator :: Class Simulator
[hide private]
[frames] | no frames]

Class Simulator

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
              host.Host --+    
                          |    
       local_host.LocalHost --+
                              |
                             Simulator

A 'Simulator' is a semi-hosted simulation environment.

The local file system is shared with the simulated machine. A simulator is used to execute programs.

Nested Classes [hide private]

Inherited from host.Host: Executable

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, path, arguments, environment=None, timeout=-1)
Run a program on the remote host.
source code

Inherited from local_host.LocalHost: DeleteFile, DownloadFile, UploadAndRun, UploadFile

Inherited from local_host.LocalHost (private): _SameFile

Inherited from host.Host: __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  simulator = TextField(description= """The simulation program.""")
  simulator_args = SetField(TextField(description= """Arguments ...

Inherited from host.Host: kind

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, path, arguments, environment=None, timeout=-1)

source code 

Run a program on the remote host.

'path' -- The name of the program to run, on the remote host. If 'relative' is true, or if 'path' is not an absolute path but does contain at least one directory separator, then 'path' is interpreted relative to the default directory. Otherwise, 'path' is used unmodified.

'arguments' -- The sequence of arguments that should be passed to the program.

'environment' -- If not 'None', a dictionary of pairs of strings to add to the environment of the running program.

'timeout' -- The number of seconds the program is permitted to execute. After the 'timeout' expires, the program will be terminated. However, in some cases (such as when using 'rsh') it will be the local side of the connection that is closed. The remote side of the connection may or may not continue to operate, depending on the vagaries of the remote operating system.

returns -- A pair '(status, output)'. The 'status' is the exit status returned by the program, or 'None' if the exit status is not available. The 'output' is a string giving the combined standard output and standard error output from the program.

Overrides: host.Host.Run
(inherited documentation)

Class Variable Details [hide private]

simulator_args

Value:
SetField(TextField(description= """Arguments to the simulation program\
."""))

././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Return.ReturnTag-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Return.ReturnTag-class.htm0000664000076400007640000001773611122067146033115 0ustar stefanstefan qm.external.DocumentTemplate.DT_Return.ReturnTag
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Return :: Class ReturnTag
[hide private]
[frames] | no frames]

Class ReturnTag

source code

Instance Methods [hide private]
 
__init__(self, args) source code
 
render(self, md) source code
 
__call__(self, md) source code
Class Variables [hide private]
  name = 'return'
  expr = None
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.sql_result_stream-module.html0000664000076400007640000001351411122067145030746 0ustar stefanstefan qm.test.classes.sql_result_stream
Package qm :: Package test :: Package classes :: Module sql_result_stream
[hide private]
[frames] | no frames]

Module sql_result_stream

source code

Classes [hide private]
  _SQLConnected
Mixin class for classes that need a database connection.
  SQLResultStream
A 'SQLResultStream' writes results out to an SQL database.
  _Buffer
A little buffering iterator with one-element rewind.
  SQLResultReader
A 'SQLResultReader' reads result in from an SQL database.
qmtest-2.4.1/share/doc/qmtest/html/manual/float-class.html0000664000076400007640000010470111122067145023074 0ustar stefanstefan float
float :: Class float
[hide private]
[frames] | no frames]

Class float

object --+
         |
        float

float(x) -> floating point number

Convert a string or number to a floating point number, if possible.

Instance Methods [hide private]
 
__abs__(x)
abs(x)
 
__add__(x, y)
x+y
 
__coerce__(x, y)
coerce(x, y)
 
__div__(x, y)
x/y
 
__divmod__(x, y)
divmod(x, y)
 
__eq__(x, y)
x==y
 
__float__(x)
float(x)
 
__floordiv__(x, y)
x//y
 
__ge__(x, y)
x>=y
 
__getattribute__(...)
x.__getattribute__('name') <==> x.name
string
__getformat__(float, typestr)
You probably don't want to use this function.
 
__getnewargs__(...)
 
__gt__(x, y)
x>y
 
__hash__(x)
hash(x)
 
__int__(x)
int(x)
 
__le__(x, y)
x<=y
 
__long__(x)
long(x)
 
__lt__(x, y)
x<y
 
__mod__(x, y)
x%y
 
__mul__(x, y)
x*y
 
__ne__(x, y)
x!=y
 
__neg__(x)
-x
a new object with type S, a subtype of T
__new__(T, S, ...)
 
__nonzero__(x)
x != 0
 
__pos__(x)
+x
 
__pow__(x, y, z=...)
pow(x, y[, z])
 
__radd__(x, y)
y+x
 
__rdiv__(x, y)
y/x
 
__rdivmod__(x, y)
divmod(y, x)
 
__repr__(x)
repr(x)
 
__rfloordiv__(x, y)
y//x
 
__rmod__(x, y)
y%x
 
__rmul__(x, y)
y*x
 
__rpow__(y, x, z=...)
pow(x, y[, z])
 
__rsub__(x, y)
y-x
 
__rtruediv__(x, y)
y/x
None
__setformat__(float, typestr, fmt)
You probably don't want to use this function.
 
__str__(x)
str(x)
 
__sub__(x, y)
x-y
 
__truediv__(x, y)
x/y

Inherited from object: __delattr__, __init__, __reduce__, __reduce_ex__, __setattr__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__getattribute__(...)

 

x.__getattribute__('name') <==> x.name

Overrides: object.__getattribute__

__getformat__(float, typestr)

 

You probably don't want to use this function. It exists mainly to be used in Python's test suite.

typestr must be 'double' or 'float'. This function returns whichever of 'unknown', 'IEEE, big-endian' or 'IEEE, little-endian' best describes the format of floating point numbers used by the C type named by typestr.

Returns: string

__hash__(x)
(Hashing function)

 

hash(x)

Overrides: object.__hash__

__new__(T, S, ...)

 
Returns: a new object with type S, a subtype of T
Overrides: object.__new__

__repr__(x)
(Representation operator)

 

repr(x)

Overrides: object.__repr__

__setformat__(float, typestr, fmt)

 

You probably don't want to use this function. It exists mainly to be used in Python's test suite.

typestr must be 'double' or 'float'. fmt must be one of 'unknown', 'IEEE, big-endian' or 'IEEE, little-endian', and in addition can only be one of the latter two if it appears to match the underlying C reality.

Overrides the automatic determination of C-level floating point type. This affects how floats are converted to and from binary strings.

Returns: None

__str__(x)
(Informal representation operator)

 

str(x)

Overrides: object.__str__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.previous_testrun-pysrc.html0000664000076400007640000013721411122067154030515 0ustar stefanstefan qm.test.classes.previous_testrun
Package qm :: Package test :: Package classes :: Module previous_testrun
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.previous_testrun

 1  ######################################################################## 
 2  # 
 3  # File:   previous_testrun.py 
 4  # Author: Stefan Seefeld 
 5  # Date:   2006-11-16 
 6  # 
 7  # Contents: 
 8  #   QMTest PreviousTestRun extension class. 
 9  # 
10  # Copyright (c) 2006 by CodeSourcery, Inc.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from qm.fields import TextField, PythonField 
21  from qm.test.expectation_database import ExpectationDatabase 
22  from qm.test.result import Result 
23  from qm.test.base import load_results 
24   
25  ######################################################################## 
26  # Classes 
27  ######################################################################## 
28   
29 -class PreviousTestRun(ExpectationDatabase):
30 """A 'PreviousTestRun' uses test results as expectations. 31 32 A 'PreviousTestRun' uses a ResultsFile such as generated by 33 'qmtest run' to determine the expected outcome for the current 34 test run.""" 35 36 file_name = TextField(description="The name of the results file.") 37 results_file = PythonField("The results file.") 38 39
40 - def __init__(self, **args):
41 42 super(PreviousTestRun, self).__init__(**args) 43 if not self.results_file: 44 self.results_file = open(self.file_name, "rb") 45 results = load_results(self.results_file, self.test_database) 46 self._results = {} 47 for r in results: 48 # Keep test results only. 49 if r.GetKind() == Result.TEST: 50 self._results[r.GetId()] = r
51 52
53 - def Lookup(self, test_id):
54 55 return self._results.get(test_id) or Result(Result.TEST, test_id)
56

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.extension.Extension-class.html0000664000076400007640000006515511122067146026404 0ustar stefanstefan qm.extension.Extension
qm :: extension :: Extension :: Class Extension
[hide private]
[frames] | no frames]

Class Extension

source code

object --+
         |
        Extension
Known Subclasses:

A class derived from 'Extension' is a QM extension.

A variety of different classes are derived from 'Extension'. All of these classes can be derived from by users to produce customized QM extensions.

'Extension' is an abstract class.

Nested Classes [hide private]
  Type
  __metaclass__
Instance Methods [hide private]
 
__init__(self, **args)
Construct a new 'Extension'.
source code
 
__getattr__(self, name) source code
 
GetClassName(self)
Return the name of the extension class.
source code
 
GetExplicitArguments(self)
Return the arguments to this extension instance.
source code
 
MakeDomElement(self, document, element=None)
Create a DOM node for 'self'.
source code
 
MakeDomDocument(self)
Create a DOM document for 'self'.
source code
 
Write(self, file)
Write an XML description of 'self' to a file.
source code

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = []
A list of the arguments to the extension class.
  kind = None
A string giving kind of extension is implemented by the class.
  _argument_list = []
A list of all the 'Field's in this class.
  _argument_dictionary = {}
A map from argument names to 'Field' instances.
  _allow_arg_names_matching_class_vars = None
True if it is OK for fields to have the same name as class variables.
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__

GetClassName(self)

source code 

Return the name of the extension class.

returns -- A string giving the name of this etension class.

GetExplicitArguments(self)

source code 

Return the arguments to this extension instance.

returns -- A dictionary mapping argument names to their values. Computed arguments are ommitted from the dictionary.

MakeDomElement(self, document, element=None)

source code 

Create a DOM node for 'self'.

'document' -- The DOM document that will contain the new element.

'element' -- If not 'None' the extension element to which items will be added. Otherwise, a new element will be created by this function.

returns -- A new DOM element corresponding to an instance of the extension class. The caller is responsible for attaching it to the 'document'.

MakeDomDocument(self)

source code 

Create a DOM document for 'self'.

'extension_class' -- A class derived from 'Extension'.

'arguments' -- The arguments to the extension class.

returns -- A new DOM document corresponding to an instance of the extension class.

Write(self, file)

source code 

Write an XML description of 'self' to a file.

'file' -- A file object to which the data should be written.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[]

kind

A string giving kind of extension is implemented by the class.

This field is used in an application-specific way; for example, QMTest has 'test' and 'target' extension classes.

Value:
None

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{}

_allow_arg_names_matching_class_vars

True if it is OK for fields to have the same name as class variables.

If this variable is set to true, it is OK for the 'arguments' to contain a field whose name is the same as a class variable. That makes the 'default_value' handling for fields fail, and is generally confusing.

This module no longer allows such classes, unless this variable is set to true. That permits legacy extension classes to continue working, while preventing new extension classes from making the same mistake.

Value:
None

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.extension-pysrc.html0000664000076400007640000070727511122067152024467 0ustar stefanstefan qm.extension
Package qm :: Module extension
[hide private]
[frames] | no frames]

Source Code for Module qm.extension

  1  ######################################################################## 
  2  # 
  3  # File:   extension.py 
  4  # Author: Mark Mitchell 
  5  # Date:   07/31/2002 
  6  # 
  7  # Contents: 
  8  #   Extension 
  9  # 
 10  # Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ######################################################################## 
 17   
 18  import os.path 
 19  import qm 
 20  from qm.fields import Field 
 21  import StringIO 
 22  import tokenize 
 23  import xml 
 24   
 25  ######################################################################## 
 26  # Classes 
 27  ######################################################################## 
 28   
29 -class Extension(object):
30 """A class derived from 'Extension' is a QM extension. 31 32 A variety of different classes are derived from 'Extension'. All 33 of these classes can be derived from by users to produce 34 customized QM extensions. 35 36 'Extension' is an abstract class.""" 37
38 - class Type(type):
39
40 - def __init__(cls, name, bases, dict):
41 """Generate an '_argument_dictionary' holding all the 42 'Field' objects. Then replace 'Field' objects by their 43 values for convenient use inside the code.""" 44 45 # List all base classes that are themselves of type Extension. 46 # 47 # 'Extension' isn't known at this point so all we can do to find 48 # Extension base classes is test whether __metaclass__ is defined 49 # and if so, whether it is a base class of the metaclass of cls. 50 type = cls.__metaclass__ 51 def is_extension(base): 52 metaclass = getattr(base, '__metaclass__', None) 53 return metaclass and issubclass(type, metaclass)
54 55 hierarchy = [base for base in bases if is_extension(base)] 56 57 parameters = {} 58 for c in hierarchy: 59 parameters.update(c._argument_dictionary) 60 # Now set parameters from class variables of type 'Field'. 61 for key, field in dict.iteritems(): 62 if isinstance(field, Field): 63 field.SetName(key) 64 parameters[key] = field 65 66 # For backward compatibility, inject all members of the 67 # 'arguments' list into the dict, if it is indeed a list of fields. 68 arguments = dict.get('arguments', []) 69 if (type(arguments) is list and 70 len(arguments) > 0 and 71 isinstance(arguments[0], Field)): 72 for field in arguments: 73 # Only allow name collisions between arguments and 74 # class variables if _allow_arg_names_matching_class_vars 75 # evaluates to True. 76 if (hasattr(cls, field.GetName()) 77 and not cls._argument_dictionary.has_key(field.GetName()) 78 and not cls._allow_arg_names_matching_class_vars): 79 raise qm.common.QMException, \ 80 qm.error("ext arg name matches class var", 81 class_name = name, 82 argument_name = field.GetName()) 83 parameters[field.GetName()] = field 84 85 setattr(cls, '_argument_dictionary', parameters) 86 setattr(cls, '_argument_list', parameters.values()) 87 88 # Finally set default values. 89 for i in parameters: 90 setattr(cls, i, parameters[i].GetDefaultValue())
91 92 __metaclass__ = Type 93 94 arguments = [] 95 """A list of the arguments to the extension class. 96 97 Each element of this list should be an instance of 'Field'. The 98 'Field' instance describes the argument. 99 100 Derived classes may redefine this class variable. However, 101 derived classes should not explicitly include the arguments from 102 base classes; QMTest will automatically combine all the arguments 103 found throughout the class hierarchy.""" 104 105 kind = None 106 """A string giving kind of extension is implemented by the class. 107 108 This field is used in an application-specific way; for example, 109 QMTest has 'test' and 'target' extension classes.""" 110 111 _argument_list = None 112 """A list of all the 'Field's in this class. 113 114 This list combines the complete list of 'arguments'. 'Field's 115 appear in the order reached by a pre-order breadth-first traversal 116 of the hierarchy, starting from the most derived class.""" 117 118 _argument_dictionary = None 119 """A map from argument names to 'Field' instances. 120 121 A map from the names of arguments for this class to the 122 corresponding 'Field'.""" 123 124 _allow_arg_names_matching_class_vars = None 125 """True if it is OK for fields to have the same name as class variables. 126 127 If this variable is set to true, it is OK for the 'arguments' to 128 contain a field whose name is the same as a class variable. That 129 makes the 'default_value' handling for fields fail, and is 130 generally confusing. 131 132 This module no longer allows such classes, unless this variable is 133 set to true. That permits legacy extension classes to continue 134 working, while preventing new extension classes from making the 135 same mistake.""" 136 137
138 - def __init__(self, **args):
139 """Construct a new 'Extension'. 140 141 'args': Keyword arguments providing values for Extension parameters. 142 The values should be appropriate for the corresponding fields. 143 Derived classes must pass along any unrecognized keyword 144 arguments to this method so that additional arguments 145 can be added in the future without necessitating changes to 146 derived classes. 147 148 This method will place all of the arguments into this objects 149 instance dictionary. 150 151 Derived classes may override this method, but should call this 152 method during their processing.""" 153 154 # Make sure that all the arguments actually correspond to 155 # 'Field's for this class. 156 if __debug__: 157 dictionary = get_class_arguments_as_dictionary(self.__class__) 158 for a, v in args.items(): 159 if not dictionary.has_key(a): 160 raise AttributeError, a 161 162 # Remember the arguments provided. 163 self.__dict__.update(args)
164
165 - def __getattr__(self, name):
166 167 # Perhaps a default value for a class argument should be used. 168 field = get_class_arguments_as_dictionary(self.__class__).get(name) 169 if field is None: 170 raise AttributeError, name 171 return field.GetDefaultValue()
172 173
174 - def GetClassName(self):
175 """Return the name of the extension class. 176 177 returns -- A string giving the name of this etension class.""" 178 179 return get_extension_class_name(self.__class__)
180 181
182 - def GetExplicitArguments(self):
183 """Return the arguments to this extension instance. 184 185 returns -- A dictionary mapping argument names to their 186 values. Computed arguments are ommitted from the 187 dictionary.""" 188 189 # Get all of the arguments. 190 arguments = get_class_arguments_as_dictionary(self.__class__) 191 # Determine which subset of the 'arguments' have been set 192 # explicitly. 193 explicit_arguments = {} 194 for name, field in arguments.items(): 195 # Do not record computed fields. 196 if field.IsComputed(): 197 continue 198 if self.__dict__.has_key(name): 199 explicit_arguments[name] = self.__dict__[name] 200 201 return explicit_arguments
202 203
204 - def MakeDomElement(self, document, element = None):
205 """Create a DOM node for 'self'. 206 207 'document' -- The DOM document that will contain the new 208 element. 209 210 'element' -- If not 'None' the extension element to which items 211 will be added. Otherwise, a new element will be created by this 212 function. 213 214 returns -- A new DOM element corresponding to an instance of the 215 extension class. The caller is responsible for attaching it to 216 the 'document'.""" 217 218 return make_dom_element(self.__class__, 219 self.GetExplicitArguments(), 220 document, element)
221 222
223 - def MakeDomDocument(self):
224 """Create a DOM document for 'self'. 225 226 'extension_class' -- A class derived from 'Extension'. 227 228 'arguments' -- The arguments to the extension class. 229 230 returns -- A new DOM document corresponding to an instance of the 231 extension class.""" 232 233 document = qm.xmlutil.create_dom_document( 234 public_id = "Extension", 235 document_element_tag = "extension" 236 ) 237 self.MakeDomElement(document, document.documentElement) 238 return document
239 240
241 - def Write(self, file):
242 """Write an XML description of 'self' to a file. 243 244 'file' -- A file object to which the data should be written.""" 245 246 document = self.MakeDomDocument() 247 document.writexml(file)
248 249 250 251 ######################################################################## 252 # Functions 253 ######################################################################## 254
255 -def get_class_arguments(extension_class):
256 """Return the arguments associated with 'extension_class'. 257 258 'extension_class' -- A class derived from 'Extension'. 259 260 returns -- A list of 'Field' objects containing all of the 261 arguments in the class hierarchy.""" 262 263 assert issubclass(extension_class, Extension) 264 return extension_class._argument_list
265 266
267 -def get_class_arguments_as_dictionary(extension_class):
268 """Return the arguments associated with 'extension_class'. 269 270 'extension_class' -- A class derived from 'Extension'. 271 272 returns -- A dictionary mapping argument names to 'Field' 273 objects. The dictionary contains all of the arguments in the 274 class hierarchy.""" 275 276 assert issubclass(extension_class, Extension) 277 return extension_class._argument_dictionary
278 279
280 -def get_class_description(extension_class, brief=0):
281 """Return a brief description of the extension class 'extension_class'. 282 283 'extension_class' -- A class derived from 'Extension'. 284 285 'brief' -- If true, return a brief (one-line) description of the 286 extension class. 287 288 returns -- A structured text description of 'extension_class'.""" 289 290 assert issubclass(extension_class, Extension) 291 292 # Extract the class's doc string. 293 doc_string = extension_class.__doc__ 294 if doc_string is not None: 295 if brief: 296 doc_string = qm.structured_text.get_first(doc_string) 297 return doc_string 298 else: 299 return "&nbsp;"
300 301
302 -def get_extension_class_name(extension_class):
303 """Return the name of 'extension_class'. 304 305 'extension_class' -- A class derived from 'Extension'. 306 307 returns -- The name of 'extension_class'. This is the name that 308 is used when users refer to the class.""" 309 310 assert issubclass(extension_class, Extension) 311 312 module = extension_class.__module__.split(".")[-1] 313 return module + "." + extension_class.__name__
314 315
316 -def validate_arguments(extension_class, arguments):
317 """Validate the 'arguments' to the 'extension_class'. 318 319 'extension_class' -- A class derived from 'Extension'. 320 321 'arguments' -- A dictionary mapping argument names (strings) to 322 values (strings). 323 324 returns -- A dictionary mapping 'Field's to values. 325 326 Check that each of the 'arguments' is a valid argument to 327 'extension_class'. If so, the argumets are converted as required 328 by the 'Field', and the dictionary returned contains the converted 329 values. Otherwise, an exception is raised.""" 330 331 assert issubclass(extension_class, Extension) 332 333 # We have not converted any arguments yet. 334 converted_arguments = {} 335 336 # Check that there are no arguments that do not apply to this 337 # class. 338 class_arguments = get_class_arguments_as_dictionary(extension_class) 339 for name, value in arguments.items(): 340 field = class_arguments.get(name) 341 if not field: 342 raise qm.QMException, \ 343 qm.error("unexpected extension argument", 344 name = name, 345 class_name \ 346 = get_extension_class_name(extension_class)) 347 if field.IsComputed(): 348 raise qm.QMException, \ 349 qm.error("value provided for computed field", 350 name = name, 351 class_name \ 352 = get_extension_class_name(extension_class)) 353 converted_arguments[name] = field.ParseTextValue(value) 354 355 return converted_arguments
356 357
358 -def make_dom_element(extension_class, arguments, document, element = None):
359 """Create a DOM node for an instance of 'extension_class'. 360 361 'extension_class' -- A class derived from 'Extension'. 362 363 'arguments' -- The arguments to the extension class. 364 365 'document' -- The DOM document that will contain the new 366 element. 367 368 'element' -- If not 'None' the extension element to which items 369 will be added. Otherwise, a new element will be created by this 370 function. 371 372 returns -- A new DOM element corresponding to an instance of the 373 extension class. The caller is responsible for attaching it to 374 the 'document'.""" 375 376 # Get the dictionary of 'Field's for this extension class. 377 field_dictionary = get_class_arguments_as_dictionary(extension_class) 378 379 # Create the element. 380 if element: 381 extension_element = element 382 else: 383 extension_element = document.createElement("extension") 384 # Create an attribute describing the kind of extension. 385 if extension_class.kind: 386 extension_element.setAttribute("kind", extension_class.kind) 387 # Create an attribute naming the extension class. 388 extension_element.setAttribute("class", 389 get_extension_class_name(extension_class)) 390 # Create an element for each of the arguments. 391 for argument_name, value in arguments.items(): 392 # Skip computed arguments. 393 field = field_dictionary[argument_name] 394 if field.IsComputed(): 395 continue 396 # Create a node for the argument. 397 argument_element = document.createElement("argument") 398 # Store the name of the field. 399 argument_element.setAttribute("name", argument_name) 400 # Store the value. 401 argument_element.appendChild(field.MakeDomNodeForValue(value, 402 document)) 403 # Add the attribute node to the target. 404 extension_element.appendChild(argument_element) 405 406 return extension_element
407 408
409 -def make_dom_document(extension_class, arguments):
410 """Create a DOM document for an instance of 'extension_class'. 411 412 'extension_class' -- A class derived from 'Extension'. 413 414 'arguments' -- The arguments to the extension class. 415 416 returns -- A new DOM document corresponding to an instance of the 417 extension class.""" 418 419 document = qm.xmlutil.create_dom_document( 420 public_id = "Extension", 421 document_element_tag = "extension" 422 ) 423 make_dom_element(extension_class, arguments, document, 424 document.documentElement) 425 return document
426 427 428
429 -def write_extension_file(extension_class, arguments, file):
430 """Write an XML description of an extension to 'file'. 431 432 'extension_class' -- A class derived from 'Extension'. 433 434 'arguments' -- A dictionary mapping argument names to values. 435 436 'file' -- A file object to which the data should be written.""" 437 438 document = make_dom_document(extension_class, arguments) 439 document.writexml(file)
440 441 442
443 -def parse_dom_element(element, class_loader, attachment_store = None):
444 """Parse a DOM node representing an instance of 'Extension'. 445 446 'element' -- A DOM node, of the format created by 447 'make_dom_element'. 448 449 'class_loader' -- A callable. The callable will be passed the 450 name of the extension class and must return the actual class 451 object. 452 453 'attachment_store' -- The 'AttachmentStore' in which attachments 454 can be found. 455 456 returns -- A pair ('extension_class', 'arguments') containing the 457 extension class (a class derived from 'Extension') and the 458 arguments (a dictionary mapping names to values) stored in the 459 'element'.""" 460 461 # Determine the name of the extension class. 462 class_name = element.getAttribute("class") 463 # DOM nodes created by earlier versions of QMTest encoded the 464 # class name in a separate element, so look there for backwards 465 # compatbility. 466 if not class_name: 467 class_elements = element.getElementsByTagName("class") 468 if not class_elements: 469 class_elements = element.getElementsByTagName("class-name") 470 class_element = class_elements[0] 471 class_name = qm.xmlutil.get_dom_text(class_element) 472 # Load it. 473 extension_class = class_loader(class_name) 474 475 # Get the dictionary of 'Field's for this extension class. 476 field_dictionary = get_class_arguments_as_dictionary(extension_class) 477 478 # Collect the arguments to the extension class. 479 arguments = {} 480 for argument_element in element.getElementsByTagName("argument"): 481 name = argument_element.getAttribute("name") 482 # Find the corresponding 'Field'. 483 field = field_dictionary[name] 484 # Get the DOM node for the value. It is always a element. 485 value_node \ 486 = filter(lambda e: e.nodeType == xml.dom.Node.ELEMENT_NODE, 487 argument_element.childNodes)[0] 488 # Parse the value. 489 value = field.GetValueFromDomNode(value_node, attachment_store) 490 # Python does not allow keyword arguments to have Unicode 491 # values, so we convert the name to an ordinary string. 492 arguments[str(name)] = value 493 494 return (extension_class, arguments)
495 496
497 -def read_extension_file(file, class_loader, attachment_store = None):
498 """Parse a file describing an extension instance. 499 500 'file' -- A file-like object from which the extension instance 501 will be read. 502 503 'class_loader' -- A callable. The callable will be passed the 504 name of the extension class and must return the actual class 505 object. 506 507 'attachment_store' -- The 'AttachmentStore' in which attachments 508 can be found. 509 510 returns -- A pair ('extension_class', 'arguments') containing the 511 extension class (a class derived from 'Extension') and the 512 arguments (a dictionary mapping names to values) stored in the 513 'element'.""" 514 515 document = qm.xmlutil.load_xml(file) 516 return parse_dom_element(document.documentElement, 517 class_loader, 518 attachment_store)
519 520
521 -def parse_descriptor(descriptor, class_loader, extension_loader = None):
522 """Parse a descriptor representing an instance of 'Extension'. 523 524 'descriptor' -- A string representing an instance of 'Extension'. 525 The 'descriptor' has the form 'class(arg1 = "val1", arg2 = "val2", 526 ...)'. The arguments and the parentheses are optional. 527 528 'class_loader' -- A callable that, when passed the name of the 529 extension class, will return the actual Python class object. 530 531 'extension_loader' -- A callable that loads an existing extension 532 given the name of that extension and returns a tuple '(class, 533 arguments)' where 'class' is a class derived from 'Extension'. If 534 'extension_loader' is 'None', or if the 'class' returned is 535 'None', then if a file exists named 'class', the extension is read 536 from 'class' as XML. Any arguments returned by the extension 537 loader or read from the file system are overridden by the 538 arguments explicitly provided in the descriptor. 539 540 returns -- A pair ('extension_class', 'arguments') containing the 541 extension class (a class derived from 'Extension') and the 542 arguments (a dictionary mapping names to values) stored in the 543 'element'. The 'arguments' will have already been processed by 544 'validate_arguments' by the time they are returned.""" 545 546 # Look for the opening parenthesis. 547 open_paren = descriptor.find('(') 548 if open_paren == -1: 549 # If there is no opening parenthesis, the descriptor is simply 550 # the name of an extension class. 551 class_name = descriptor 552 else: 553 # The class name is the part of the descriptor up to the 554 # parenthesis. 555 class_name = descriptor[:open_paren] 556 557 # Load the extension, if it already exists. 558 extension_class = None 559 if extension_loader: 560 extension = extension_loader(class_name) 561 if extension: 562 extension_class = extension.__class__ 563 orig_arguments = extension.GetExplicitArguments() 564 if not extension_class: 565 if os.path.exists(class_name): 566 extension_class, orig_arguments \ 567 = read_extension_file(open(filename), class_loader) 568 else: 569 extension_class = class_loader(class_name) 570 orig_arguments = {} 571 572 arguments = {} 573 574 # Parse the arguments. 575 if open_paren != -1: 576 # Create a file-like object for the remainder of the string. 577 arguments_string = descriptor[open_paren:] 578 s = StringIO.StringIO(arguments_string) 579 # Use the Python tokenizer to process the remainder of the 580 # string. 581 g = tokenize.generate_tokens(s.readline) 582 # Read the opening parenthesis. 583 tok = g.next() 584 assert tok[0] == tokenize.OP and tok[1] == "(" 585 need_comma = 0 586 # Keep going until we find the closing parenthesis. 587 while 1: 588 tok = g.next() 589 if tok[0] == tokenize.OP and tok[1] == ")": 590 break 591 # All arguments but the first must be separated by commas. 592 if need_comma: 593 if tok[0] != tokenize.OP or tok[1] != ",": 594 raise qm.QMException, \ 595 qm.error("invalid descriptor syntax", 596 start = arguments_string[tok[2][1]:]) 597 tok = g.next() 598 # Read the argument name. 599 if tok[0] != tokenize.NAME: 600 raise qm.QMException, \ 601 qm.error("invalid descriptor syntax", 602 start = arguments_string[tok[2][1]:]) 603 name = tok[1] 604 # Read the '='. 605 tok = g.next() 606 if tok[0] != tokenize.OP or tok[1] != "=": 607 raise qm.QMException, \ 608 qm.error("invalid descriptor syntax", 609 start = arguments_string[tok[2][1]:]) 610 # Read the value. 611 tok = g.next() 612 if tok[0] != tokenize.STRING: 613 raise qm.QMException, \ 614 qm.error("invalid descriptor syntax", 615 start = arguments_string[tok[2][1]:]) 616 # The token string will have surrounding quotes. By 617 # running it through "eval", we get at the underlying 618 # value. 619 value = eval(tok[1]) 620 arguments[name] = value 621 # The next argument must be preceded by a comma. 622 need_comma = 1 623 # There shouldn't be anything left at this point. 624 tok = g.next() 625 if not tokenize.ISEOF(tok[0]): 626 raise qm.QMException, \ 627 qm.error("invalid descriptor syntax", 628 start = arguments_string[tok[2][1]:]) 629 630 # Process the arguments. 631 arguments = validate_arguments(extension_class, arguments) 632 # Use the explict arguments to override any specified in the file. 633 orig_arguments.update(arguments) 634 635 return (extension_class, orig_arguments)
636

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python.StringExceptionTest-class.html0000664000076400007640000004232711122067147032331 0ustar stefanstefan qm.test.classes.python.StringExceptionTest
Package qm :: Package test :: Package classes :: Module python :: Class StringExceptionTest
[hide private]
[frames] | no frames]

Class StringExceptionTest

source code

         object --+                
                  |                
extension.Extension --+            
                      |            
      runnable.Runnable --+        
                          |        
                  test.Test --+    
                              |    
              BaseExceptionTest --+
                                  |
                                 StringExceptionTest

Check that the specified Python code raises a string exception.

A 'StringExceptionTest' checks that the specified code throws an exception. The exception must be a string and must have the expected value.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
MakeResult(self, exc_info, result)
Check the exception in 'exc_info' and construct the result.
source code

Inherited from BaseExceptionTest: CheckArgument, Run

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "exception_text", title...
A list of the arguments to the extension class.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

MakeResult(self, exc_info, result)

source code 

Check the exception in 'exc_info' and construct the result.

'result' -- The result object for this test.

Overrides: BaseExceptionTest.MakeResult
(inherited documentation)

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "exception_text", title= "Exception Text", \
description= "The expected exception string.", default_value= "excepti\
on")]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_In-pysrc.html0000664000076400007640000074437711122067162030507 0ustar stefanstefan qm.external.DocumentTemplate.DT_In
Package qm :: Package external :: Package DocumentTemplate :: Module DT_In
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_In

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  '''Sequence insertion 
 14   
 15         A sequence may be inserted using an 'in' command.  The 'in' 
 16         command specifies the name of a sequence object and text to 
 17         be inserted for each element in the sequence. 
 18   
 19         The EPFS syntax for the in command is:: 
 20   
 21            %(in name)[ 
 22                 text 
 23            %(in name)] 
 24   
 25         The HTML syntax for the in command is:: 
 26   
 27            <!--#in name--> 
 28                 text 
 29            <!--#/in name--> 
 30   
 31        See the example below that shows how 'if', 'else', and 'in' commands 
 32        may be combined to display a possibly empty list of objects. 
 33   
 34        The text included within an 'in' command will be refered to 
 35        as an 'in' block. 
 36   
 37      Synopsis 
 38   
 39        If the variable 'sequence' exists as a sequence, a simple case 
 40        of the 'in' tag is used as follows:: 
 41   
 42           <!--#in sequence-->some markup<!--#/in--> 
 43   
 44        A more complete case is used as follows:: 
 45   
 46          <!--#in sequence sort=age--> 
 47            <!--#var sequence-number-->) <!--#var age--> 
 48          <!--#/in--> 
 49   
 50      Attributes 
 51   
 52        sort -- Define the sort order for sequence items.  Parameter to the 
 53        attribute is either a sort option, or list of sort options separated 
 54        by comma.  Every sort option consists of variable name, optional 
 55        comparison function name (default is cmp) and optional sort order 
 56        (default is asc). 
 57            Examples: sort="date" or sort="date,time" or 
 58        sort="title/locale,date/cmp/desc". If you want to specify sort order, 
 59        you cannot omit the function; use cmp for standard comparison. 
 60            Few predefined comparison functions available: standard cmp, 
 61        nocase (ignore string case), strcoll (alias "locale"), 
 62        strcoll_nocase (alias "locale_nocase"). Locale functions are 
 63        available only if module locale is already imported (you started Zope 
 64        with -L locale). 
 65   
 66        sort_expr -- The "sort" attribute accepts only static list of 
 67        sort options. This calculated parameter allows you to calculate the 
 68        list of sort options on the fly. 
 69   
 70        sort_expr -- This allows an expression to control sort order. 
 71   
 72        reverse -- Reverse the sequence (may be combined with sort).  Note 
 73        that this can cause a huge memory use in lazy activation instances. 
 74   
 75        reverse_expr -- This calculated parameter allows you to calculate the 
 76        need of reversing on the fly. 
 77   
 78        Within an 'in' block, variables are substituted from the 
 79        elements of the iteration unless the 'no_push_item' optional 
 80        is specified.  The elements may be either instance or mapping 
 81        objects.  In addition, the variables: 
 82   
 83           'sequence-item' -- The element. 
 84   
 85           'sequence-var-nnn' -- The value of a specific named attribute 
 86             of the item, where 'nnn' is the name.  For example, to get 
 87             an items 'title' attribute, use 'sequence-var-title'.  This 
 88             construct is most useful in an 'if' tag to test whether an 
 89             attribute is present, because the attribute lookup will be 
 90             extended to the full document template namespace. 
 91   
 92           'sequence-key' -- The key associated with the element in an 
 93             items list. See below. 
 94   
 95           'sequence-index' -- The index, starting from 0, of the 
 96             element within the sequence. 
 97   
 98           'sequence-number' -- The index, starting from 1, of the 
 99             element within the sequence. 
100   
101           'sequence-letter' -- The index, starting from 'a', of the 
102             element within the sequence. 
103   
104           'sequence-Letter' -- The index, starting from 'A', of the 
105             element within the sequence. 
106   
107           'sequence-roman' -- The index, starting from 'i', of the 
108             element within the sequence. 
109   
110           'sequence-Roman' -- The index, starting from 'I', of the 
111             element within the sequence. 
112   
113           'sequence-start' -- A variable that is true if the element 
114             being displayed is the first of the displayed elements, 
115             and false otherwise. 
116   
117           'sequence-end' -- A variable that is true if the element 
118             being displayed is the last of the displayed elements, 
119             and false otherwise. 
120   
121        are defined for each element. 
122   
123        Normally, 'in' blocks are used to iterate over sequences of 
124        instances.  If the optional parameter 'mapping' is specified 
125        after the sequence name, then the elements of the sequence 
126        will be treated as mapping objects. 
127   
128        An 'in' command may be used to iterate over a sequence of 
129        dictionary items.  If the elements of the iteration are 
130        two-element tuples, then then the template code given in the 
131        'in' block will be applied to the second element of each 
132        tuple and may use a variable, 'sequence-key' to access the 
133        first element in each tuple. 
134   
135      Batch sequence insertion 
136   
137        When displaying a large number of objects, it is sometimes 
138        desirable to display just a sub-sequence of the data. 
139        An 'in' command may have optional parameters, 
140        as in:: 
141   
142            <!--#in values start=start_var size=7--> 
143   
144        The parameter values may be either integer literals or 
145        variable names. 
146   
147        Up to five parameters may be set: 
148   
149            'start'   -- The number of the first element to be shown, 
150                         where elements are numbered from 1. 
151   
152            'end'     -- The number of the last element to be shown, 
153                         where elements are numbered from 1. 
154   
155            'size'    -- The desired number of elements to be shown at 
156                         once. 
157   
158            'orphan'  -- The desired minimum number of objects to be 
159                         displayed.  The default value for this 
160                         parameter is 3. 
161   
162            'overlap' -- The desired overlap between batches. The 
163                         default is no overlap. 
164   
165        Typically, only 'start' and 'size' will be specified. 
166   
167        When batch insertion is used, several additional variables are 
168        defined for use within the sequence insertion text: 
169   
170            'sequence-query' -- The original query string given in a get 
171               request with the form variable named in the 'start' 
172               attribute removed.  This is extremely useful when 
173               building URLs to fetch another batch. 
174   
175               To see how this is used, consider the following example:: 
176   
177                   <!--#in search_results size=20 start=batch_start--> 
178   
179                      ... display rows 
180   
181                      <!--#if sequence-end--> <!--#if next-sequence--> 
182                        <a href="<!--#var URL-->/<!--#var sequence-query 
183                            -->&batch_start=<!--#var 
184                            next-sequence-start-number-->"> 
185                        (Next <!--#var next-sequence-size--> results) 
186                        </a> 
187                      <!--#/if--> <!--#/if--> 
188   
189                   <!--#/in--> 
190   
191               If the original URL is: 'foo/bar?x=1&y=2', then the 
192               rendered text (after row data are displayed) will be:: 
193   
194                        <a href="foo/bar?x=1&amp;y=2&amp;batch_start=20"> 
195                        (Next 20 results) 
196                        </a> 
197   
198               If the original URL is: 'foo/bar?batch_start=10&x=1&y=2', 
199               then the rendered text (after row data are displayed) 
200               will be:: 
201   
202                        <a href="foo/bar?x=1&amp;y=2&amp;batch_start=30"> 
203                        (Next 20 results) 
204                        </a> 
205   
206            'sequence-step-start-index' -- The index, starting from 0, 
207               of the start of the current batch. 
208   
209            'sequence-step-end-index' -- The index, starting from 0, of 
210               the end of the current batch. 
211   
212            'sequence-step-size' -- The batch size used. 
213   
214            'previous-sequence' -- This variable will be true when the 
215               first element is displayed and when the first element 
216               displayed is not the first element in the sequence. 
217   
218            'previous-sequence-start-index' -- The index, starting from 
219               0, of the start of the batch previous to the current 
220               batch. 
221   
222            'previous-sequence-end-index' -- The index, starting from 
223               0, of the end of the batch previous to the current 
224               batch. 
225   
226            'previous-sequence-size' -- The size of the batch previous to 
227               the current batch. 
228   
229            'previous-batches' -- A sequence of mapping objects 
230               containing information about all of the batches prior 
231               to the batch being displayed. 
232   
233               Each of these mapping objects include the following 
234               variables: 
235   
236                  batch-start-index -- The index, starting from 
237                     0, of the beginning of the batch. 
238   
239                  batch-end-index -- The index, starting from 
240                     0, of the end of the batch. 
241   
242                  batch-size -- The size of the batch. 
243   
244            'next-sequence' -- This variable will be true when the last 
245               element is displayed and when the last element 
246               displayed is not the last element in the sequence. 
247   
248            'next-sequence-start-index' -- The index, starting from 
249               0, of the start of the batch after the current 
250               batch. 
251   
252            'next-sequence-end-index' -- The index, starting from 
253               0, of the end of the batch after the current 
254               batch. 
255   
256            'next-sequence-size' -- The size of the batch after 
257               the current batch. 
258   
259            'next-batches' -- A sequence of mapping objects 
260               containing information about all of the batches after 
261               the batch being displayed. 
262   
263               Each of these mapping objects include the following 
264               variables: 
265   
266                  batch-start-index -- The index, starting from 
267                     0, of the beginning of the batch. 
268   
269                  batch-end-index -- The index, starting from 
270                     0, of the end of the batch. 
271   
272                  batch-size -- The size of the batch. 
273   
274        For each of the variables listed above with names ending in 
275        "-index", there are variables with names ending in "-number", 
276        "-roman", "-Roman", "-letter", and "-Letter" that are indexed 
277        from 1, "i", "I", "a", and "A", respectively.  In addition, 
278        for every one of these variables there are variables with 
279        names ending in "-var-xxx", where "xxx" is an element 
280        attribute name or key. 
281   
282      Summary statistics 
283   
284        When performing sequence insertion, special variables may be 
285        used to obtain summary statistics.  To obtain a summary 
286        statistic for a variable, use the variable name: 
287        'statistic-name', where 'statistic' is a statistic name and 
288        'name' is the name of a data variable. 
289   
290        Currently supported statistic names are: 
291   
292          total -- The total of numeric values. 
293   
294          count -- The total number of non-missing values. 
295   
296          min -- The minimum of non-missing values. 
297   
298          max -- The maximum of non-missing values. 
299   
300          median -- The median of non-missing values. 
301   
302          mean -- The mean of numeric values values. 
303   
304          variance -- The variance of numeric values computed with a 
305            degrees of freedom equal to the count - 1. 
306   
307          variance-n -- The variance of numeric values computed with a 
308            degrees of freedom equal to the count. 
309   
310          standard-deviation -- The standard deviation of numeric values 
311            computed with a degrees of freedom equal to the count - 1. 
312   
313          standard-deviation-n -- The standard deviation of numeric 
314            values computed with a degrees of freedom equal to the count. 
315   
316        Missing values are either 'None' or the attribute 'Value' 
317        of the module 'Missing', if present. 
318   
319      'else' continuation tag within in 
320   
321        An 'else' tag may be used as a continuation tag in the 'in' tag. 
322        The source after the 'else' tag is inserted if: 
323   
324          - The sequence given to the 'in' tag is of zero length, or 
325   
326          - The 'previous' attribute was used and their are no 
327            previous batches, or 
328   
329          - The 'next' attribute was used and their are no 
330            next batches, or 
331   
332  ''' #' 
333   
334  __rcs_id__='$Id: DT_In.py 1069 2008-11-13 21:55:43Z stefan $' 
335  __version__='$Revision: 1069 $'[11:-2] 
336   
337  from DT_Util import ParseError, parse_params, name_param, str 
338  from DT_Util import render_blocks, InstanceDict, ValidationError, VSEval, expr_globals 
339  import re 
340  from DT_InSV import sequence_variables, opt 
341  TupleType=type(()) 
342   
343 -class InFactory:
344 blockContinuations=('else',) 345 name='in' 346
347 - def __call__(self, blocks):
348 i=InClass(blocks) 349 if i.batch: return i.renderwb 350 else: return i.renderwob
351 352 In=InFactory() 353
354 -class InClass:
355 elses=None 356 expr=sort=batch=mapping=None 357 start_name_re=None 358 reverse=None 359 sort_expr=reverse_expr=None 360
361 - def __init__(self, blocks):
362 tname, args, section = blocks[0] 363 args=parse_params(args, name='', start='1',end='-1',size='10', 364 orphan='3',overlap='1',mapping=1, 365 skip_unauthorized=1, 366 previous=1, next=1, expr='', sort='', 367 reverse=1, sort_expr='', reverse_expr='') 368 self.args=args 369 has_key=args.has_key 370 371 if has_key('sort'): 372 self.sort=sort=args['sort'] 373 if sort=='sequence-item': self.sort='' 374 375 if has_key('sort_expr'): 376 self.sort_expr=VSEval.Eval(args['sort_expr'], expr_globals) 377 378 if has_key('reverse_expr'): 379 self.reverse_expr=VSEval.Eval(args['reverse_expr'], expr_globals) 380 381 if has_key('reverse'): 382 self.reverse=args['reverse'] 383 384 if has_key('mapping'): self.mapping=args['mapping'] 385 for n in 'start', 'size', 'end': 386 if has_key(n): self.batch=1 387 388 for n in 'orphan','overlap','previous','next': 389 if has_key(n) and not self.batch: 390 raise ParseError, ( 391 """ 392 The %s attribute was used but neither of the 393 <code>start</code>, <code>end</code>, or <code>size</code> 394 attributes were used. 395 """ % n, 'in') 396 397 if has_key('start'): 398 v=args['start'] 399 if type(v)==type(''): 400 try: int(v) 401 except: 402 403 self.start_name_re=re.compile( 404 '&+'+ 405 ''.join(["[%s]" % c for c in v])+ 406 '=[0-9]+&+') 407 408 name,expr=name_param(args,'in',1) 409 if expr is not None: expr=expr.eval 410 self.__name__, self.expr = name, expr 411 self.section=section.blocks 412 if len(blocks) > 1: 413 if len(blocks) != 2: raise ParseError, ( 414 'too many else blocks', 'in') 415 tname, args, section = blocks[1] 416 args=parse_params(args, name='') 417 if args: 418 ename=name_param(args) 419 if ename != name: 420 raise ParseError, ( 421 'name in else does not match in', 'in') 422 self.elses=section.blocks
423 424
425 - def renderwb(self, md):
426 expr=self.expr 427 name=self.__name__ 428 if expr is None: 429 sequence=md[name] 430 cache={ name: sequence } 431 else: 432 sequence=expr(md) 433 cache=None 434 435 if not sequence: 436 if self.elses: return render_blocks(self.elses, md) 437 return '' 438 439 if type(sequence) is type(''): 440 raise 'InError', ( 441 'Strings are not allowed as input to the in tag.') 442 443 444 section=self.section 445 params=self.args 446 447 mapping=self.mapping 448 449 if self.sort_expr is not None: 450 self.sort=self.sort_expr.eval(md) 451 sequence=self.sort_sequence(sequence) 452 elif self.sort is not None: 453 sequence=self.sort_sequence(sequence) 454 455 if self.reverse_expr is not None and self.reverse_expr.eval(md): 456 sequence=self.reverse_sequence(sequence) 457 elif self.reverse is not None: 458 sequence=self.reverse_sequence(sequence) 459 460 next=previous=0 461 try: start=int_param(params,md,'start',0) 462 except: start=1 463 end=int_param(params,md,'end',0) 464 size=int_param(params,md,'size',0) 465 overlap=int_param(params,md,'overlap',0) 466 orphan=int_param(params,md,'orphan','3') 467 start,end,sz=opt(start,end,size,orphan,sequence) 468 if params.has_key('next'): next=1 469 if params.has_key('previous'): previous=1 470 471 last=end-1 472 first=start-1 473 474 try: query_string=md['QUERY_STRING'] 475 except: query_string='' 476 477 vars=sequence_variables(sequence,'?'+query_string,self.start_name_re) 478 kw=vars.data 479 kw['mapping']=mapping 480 kw['sequence-step-size']=sz 481 kw['sequence-step-overlap']=overlap 482 kw['sequence-step-start']=start 483 kw['sequence-step-end']=end 484 kw['sequence-step-start-index']=start-1 485 kw['sequence-step-end-index']=end-1 486 kw['sequence-step-orphan']=orphan 487 488 push=md._push 489 pop=md._pop 490 render=render_blocks 491 492 if cache: push(cache) 493 push(vars) 494 try: 495 if previous: 496 if first > 0: 497 pstart,pend,psize=opt(0,first+overlap, 498 sz,orphan,sequence) 499 kw['previous-sequence']=1 500 kw['previous-sequence-start-index']=pstart-1 501 kw['previous-sequence-end-index']=pend-1 502 kw['previous-sequence-size']=pend+1-pstart 503 result=render(section,md) 504 505 elif self.elses: result=render(self.elses, md) 506 else: result='' 507 elif next: 508 try: 509 # The following line is a sneaky way to test whether 510 # there are more items, without actually 511 # computing a length: 512 sequence[end] 513 except IndexError: 514 if self.elses: result=render(self.elses, md) 515 else: result='' 516 else: 517 pstart,pend,psize=opt(end+1-overlap,0, 518 sz,orphan,sequence) 519 kw['next-sequence']=1 520 kw['next-sequence-start-index']=pstart-1 521 kw['next-sequence-end-index']=pend-1 522 kw['next-sequence-size']=pend+1-pstart 523 result=render(section,md) 524 else: 525 result = [] 526 append=result.append 527 validate=md.validate 528 for index in range(first,end): 529 if index==first and index > 0: 530 pstart,pend,psize=opt(0,index+overlap, 531 sz,orphan,sequence) 532 kw['previous-sequence']=1 533 kw['previous-sequence-start-index']=pstart-1 534 kw['previous-sequence-end-index']=pend-1 535 kw['previous-sequence-size']=pend+1-pstart 536 else: 537 kw['previous-sequence']=0 538 if index==last: 539 try: 540 # The following line is a sneaky way to 541 # test whether there are more items, 542 # without actually computing a length: 543 sequence[end] 544 pstart,pend,psize=opt(end+1-overlap,0, 545 sz,orphan,sequence) 546 kw['previous-sequence']=0 547 kw['next-sequence']=1 548 kw['next-sequence-start-index']=pstart-1 549 kw['next-sequence-end-index']=pend-1 550 kw['next-sequence-size']=pend+1-pstart 551 except: pass 552 553 if index==last: kw['sequence-end']=1 554 555 client=sequence[index] 556 557 if validate is not None: 558 try: vv=validate(sequence,sequence,None,client,md) 559 except: vv=0 560 if not vv: 561 if (params.has_key('skip_unauthorized') and 562 params['skip_unauthorized']): 563 if index==first: kw['sequence-start']=0 564 continue 565 raise ValidationError, index 566 567 kw['sequence-index']=index 568 if type(client)==TupleType and len(client)==2: 569 client=client[1] 570 571 if mapping: push(client) 572 else: push(InstanceDict(client, md)) 573 574 try: append(render(section, md)) 575 finally: pop(1) 576 577 if index==first: kw['sequence-start']=0 578 579 580 result=''.join(result) 581 582 finally: 583 if cache: pop() 584 pop() 585 586 return result
587
588 - def renderwob(self, md):
589 """RENDER WithOutBatch""" 590 expr=self.expr 591 name=self.__name__ 592 if expr is None: 593 sequence=md[name] 594 cache={ name: sequence } 595 else: 596 sequence=expr(md) 597 cache=None 598 599 if not sequence: 600 if self.elses: return render_blocks(self.elses, md) 601 return '' 602 603 if type(sequence) is type(''): 604 raise 'InError', ( 605 'Strings are not allowed as input to the in tag.') 606 607 section=self.section 608 mapping=self.mapping 609 610 611 if self.sort_expr is not None: 612 self.sort=self.sort_expr.eval(md) 613 sequence=self.sort_sequence(sequence) 614 elif self.sort is not None: 615 sequence=self.sort_sequence(sequence) 616 617 if self.reverse_expr is not None and self.reverse_expr.eval(md): 618 sequence=self.reverse_sequence(sequence) 619 elif self.reverse is not None: 620 sequence=self.reverse_sequence(sequence) 621 622 vars=sequence_variables(sequence) 623 kw=vars.data 624 kw['mapping']=mapping 625 626 l=len(sequence) 627 last=l-1 628 629 push=md._push 630 pop=md._pop 631 render=render_blocks 632 633 if cache: push(cache) 634 push(vars) 635 try: 636 result = [] 637 append=result.append 638 validate=md.validate 639 for index in range(l): 640 if index==last: kw['sequence-end']=1 641 client=sequence[index] 642 643 if validate is not None: 644 try: vv=validate(sequence,sequence,None,client,md) 645 except: vv=0 646 if not vv: 647 if (self.args.has_key('skip_unauthorized') and 648 self.args['skip_unauthorized']): 649 if index==1: kw['sequence-start']=0 650 continue 651 raise ValidationError, index 652 653 kw['sequence-index']=index 654 if type(client)==TupleType and len(client)==2: 655 client=client[1] 656 657 if mapping: push(client) 658 else: push(InstanceDict(client, md)) 659 660 try: append(render(section, md)) 661 finally: pop() 662 if index==0: kw['sequence-start']=0 663 664 result=''.join(result) 665 666 finally: 667 if cache: pop() 668 pop() 669 670 return result
671
672 - def sort_sequence(self, sequence):
673 674 # Modified with multiple sort fields by Ross Lazarus 675 # April 7 2000 rossl@med.usyd.edu.au 676 # eg <dtml in "foo" sort=akey,anotherkey> 677 678 sort=self.sort 679 sortfields = sort.split(',') # multi sort = key1,key2 680 multsort = len(sortfields) > 1 # flag: is multiple sort 681 mapping=self.mapping 682 isort=not sort 683 684 s=[] 685 for client in sequence: 686 k = None 687 if type(client)==TupleType and len(client)==2: 688 if isort: k=client[0] 689 v=client[1] 690 else: 691 if isort: k=client 692 v=client 693 694 if sort: 695 if multsort: # More than one sort key. 696 k = [] 697 for sk in sortfields: 698 try: 699 if mapping: akey = v[sk] 700 else: akey = getattr(v, sk) 701 except AttributeError, KeyError: akey = None 702 if not basic_type(akey): 703 try: akey = akey() 704 except: pass 705 k.append(akey) 706 else: # One sort key. 707 try: 708 if mapping: k = v[sort] 709 else: k = getattr(v, sort) 710 except AttributeError, KeyError: k = None 711 if not basic_type(k): 712 try: k = k() 713 except: pass 714 715 s.append((k,client)) 716 717 s.sort() 718 719 sequence=[] 720 for k, client in s: 721 sequence.append(client) 722 return sequence
723
724 - def reverse_sequence(self, sequence):
725 s=list(sequence) 726 s.reverse() 727 return s
728 729 730 basic_type={type(''): 1, type(0): 1, type(0.0): 1, type(()): 1, type([]): 1, 731 type(None) : 1 }.has_key 732
733 -def int_param(params,md,name,default=0, st=type('')):
734 try: v=params[name] 735 except: v=default 736 if v: 737 try: v=int(v) 738 except: 739 v=md[v] 740 if type(v) is st: v=int(v) 741 return v
742

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.text_result_stream-module.html0000664000076400007640000001135711122067145031136 0ustar stefanstefan qm.test.classes.text_result_stream
Package qm :: Package test :: Package classes :: Module text_result_stream
[hide private]
[frames] | no frames]

Module text_result_stream

source code

Classes [hide private]
  TextResultStream
A 'TextResultStream' displays test results textually.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.context.ContextException-class.html0000664000076400007640000002304711122067150030346 0ustar stefanstefan qm.test.context.ContextException
Package qm :: Package test :: Module context :: Class ContextException
[hide private]
[frames] | no frames]

Class ContextException

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  ContextException

A 'ContextException' indicates an invalid context variable.

Instance Methods [hide private]
 
__init__(self, key, msg='missing context variable')
Construct a new 'ContextException'.
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, key, msg='missing context variable')
(Constructor)

source code 

Construct a new 'ContextException'.

'key' -- A string giving the context key for which no valid value was available.

'msg' -- A diagnostic identifier explaining the problem. The message string may contain a fill-in for the key.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.web-module.html0000664000076400007640000001460711122067144024127 0ustar stefanstefan web

Module web


Classes

AddressInUseError
CGIWebRequest
DtmlPage
HTTPServer
HttpRedirect
InvalidSessionError
NoSessionError
PrivilegedPortError
Session
WebRequest
WebRequestHandler
WebServer

Functions

decode_properties
decode_set_control_contents
encode_properties
encode_set_control_contents
escape
format_color
format_exception
format_structured_text
generate_error_page
generate_login_form
get_session
handle_login
handle_logout
http_return_exception
http_return_html
javascript_escape
javascript_unescape
make_button_for_popup
make_button_for_request
make_button_for_url
make_choose_control
make_help_link
make_help_link_html
make_javascript_string
make_popup_page
make_properties_control
make_set_control
make_submit_button
make_url
parse_url_query
unescape

Variables

session_id_field
sessions

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/redirect.html0000664000076400007640000003340411122067163022466 0ustar stefanstefanEpydoc Redirect Page

Epydoc Auto-redirect page

When javascript is enabled, this page will redirect URLs of the form redirect.html#dotted.name to the documentation for the object with the given fully-qualified dotted name.

 

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler_test.CompilationStep-class.html0000664000076400007640000002016011122067147032775 0ustar stefanstefan qm.test.classes.compiler_test.CompilationStep
Package qm :: Package test :: Package classes :: Module compiler_test :: Class CompilationStep
[hide private]
[frames] | no frames]

Class CompilationStep

source code

A single compilation step.

Instance Methods [hide private]
 
__init__(self, compiler, mode, files, options=[], ldflags=[], output=None, diagnostics=[])
Construct a new 'CompilationStep'.
source code
Method Details [hide private]

__init__(self, compiler, mode, files, options=[], ldflags=[], output=None, diagnostics=[])
(Constructor)

source code 

Construct a new 'CompilationStep'.

'compiler' -- A Compiler object.

'mode' -- As for 'Compiler.Compile'.

'files' -- As for 'Compiler.Compile'.

'options' -- As for 'Compiler.Compile'.

'ldflags' -- As for 'Compiler.Compile'.

'output' -- As for 'Compiler.Compile'.

'diagnostics' -- A sequence of 'Diagnostic' instances indicating diagnostic messages that are expected from this compilation step.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm-module.html0000664000076400007640000000220411122067144023341 0ustar stefanstefan qm

Module qm


Variables

prefix
version_info

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DocumentTemplate-pysrc.html0000664000076400007640000006005711122067154033007 0ustar stefanstefan qm.external.DocumentTemplate.DocumentTemplate
Package qm :: Package external :: Package DocumentTemplate :: Module DocumentTemplate
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DocumentTemplate

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  '''Document templates with fill-in fields 
 14   
 15  Document templates provide for creation of textual documents, such as 
 16  HTML pages, from template source by inserting data from python objects 
 17  and name-spaces. 
 18   
 19  When a document template is created, a collection of default values to 
 20  be inserted may be specified with a mapping object and with keyword 
 21  arguments. 
 22   
 23  A document templated may be called to create a document with values 
 24  inserted.  When called, an instance, a mapping object, and keyword 
 25  arguments may be specified to provide values to be inserted.  If an 
 26  instance is provided, the document template will try to look up values 
 27  in the instance using getattr, so inheritence of values is supported. 
 28  If an inserted value is a function, method, or class, then an attempt 
 29  will be made to call the object to obtain values.  This allows 
 30  instance methods to be included in documents. 
 31   
 32  Document templates masquerade as functions, so the python object 
 33  publisher (Bobo) will call templates that are stored as instances of 
 34  published objects. Bobo will pass the object the template was found in 
 35  and the HTTP request object. 
 36   
 37  Two source formats are supported: 
 38   
 39     Extended Python format strings (EPFS) -- 
 40        This format is based on the insertion by name format strings 
 41        of python with additional format characters, '[' and ']' to 
 42        indicate block boundaries.  In addition, parameters may be 
 43        used within formats to control how insertion is done. 
 44   
 45        For example: 
 46   
 47           %%(date fmt=DayOfWeek upper)s 
 48   
 49        causes the contents of variable 'date' to be inserted using 
 50        custom format 'DayOfWeek' and with all lower case letters 
 51        converted to upper case. 
 52   
 53     HTML -- 
 54        This format uses HTML server-side-include syntax with 
 55        commands for inserting text. Parameters may be included to 
 56        customize the operation of a command. 
 57   
 58        For example: 
 59   
 60           <!--#var total fmt=12.2f--> 
 61   
 62        is used to insert the variable 'total' with the C format 
 63        '12.2f'. 
 64   
 65  Document templates support conditional and sequence insertion 
 66   
 67      Document templates extend python string substitition rules with a 
 68      mechanism that allows conditional insertion of template text and that 
 69      allows sequences to be inserted with element-wise insertion of 
 70      template text. 
 71   
 72  Access Control 
 73   
 74      Document templates provide a basic level of access control by 
 75      preventing access to names beginning with an underscore. 
 76      Additional control may be provided by providing document templates 
 77      with a 'guarded_getattr' and 'guarded_getitem' method.  This would 
 78      typically be done by subclassing one or more of the DocumentTemplate 
 79      classes. 
 80   
 81      If provided, the the 'guarded_getattr' method will be called when 
 82      objects are accessed as instance attributes or when they are 
 83      accessed through keyed access in an expression. 
 84   
 85  Document Templates may be created 4 ways: 
 86   
 87      DocumentTemplate.String -- Creates a document templated from a 
 88          string using an extended form of python string formatting. 
 89   
 90      DocumentTemplate.File -- Creates a document templated bound to a 
 91          named file using an extended form of python string formatting. 
 92          If the object is pickled, the file name, rather than the file 
 93          contents is pickled.  When the object is unpickled, then the 
 94          file will be re-read to obtain the string.  Note that the file 
 95          will not be read until the document template is used the first 
 96          time. 
 97   
 98      DocumentTemplate.HTML -- Creates a document templated from a 
 99          string using HTML server-side-include rather than 
100          python-format-string syntax. 
101   
102      DocumentTemplate.HTMLFile -- Creates an HTML document template 
103          from a named file. 
104   
105  ''' 
106   
107   
108  __version__='$Revision: 1069 $'[11:-2] 
109   
110  ParseError='Document Template Parse Error' 
111   
112  from DT_String import String, File 
113  from DT_HTML import HTML, HTMLFile, HTMLDefault 
114  # import DT_UI # Install HTML editing 
115  from DT_Util import html_quote 
116   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.setup-pysrc.html0000664000076400007640000002070511122067160030666 0ustar stefanstefan qm.external.DocumentTemplate.setup
Package qm :: Package external :: Package DocumentTemplate :: Module setup
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.setup

1  from distutils.core import setup 
2   
3  setup(name="DocumentTemplate", 
4        version="1.0", 
5        packages = ['zope-dtml.DocumentTemplate'], 
6        package_dir = { 'zope-dtml.DocumentTemplate' : '.' }) 
7   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.process_target-module.html0000664000076400007640000001131411122067145030216 0ustar stefanstefan qm.test.classes.process_target
Package qm :: Package test :: Package classes :: Module process_target
[hide private]
[frames] | no frames]

Module process_target

source code

Classes [hide private]
  ProcessTarget
A 'ProcessTarget' runs tests in child processes.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command.ShellScriptTest-class.html0000664000076400007640000005036311122067147031534 0ustar stefanstefan qm.test.classes.command.ShellScriptTest
Package qm :: Package test :: Package classes :: Module command :: Class ShellScriptTest
[hide private]
[frames] | no frames]

Class ShellScriptTest

source code

         object --+                
                  |                
extension.Extension --+            
                      |            
      runnable.Runnable --+        
                          |        
                  test.Test --+    
                              |    
                   ExecTestBase --+
                                  |
                                 ShellScriptTest

Check a shell script's output and exit code.

A 'ShellScriptTest' runs the shell script provided and compares its standard output, standard error, and exit code with expected values. The shell script may be provided with command-line arguments and/or standard input.

QMTest determines which shell to use by the following method:

  • If the context contains the property 'ShellScriptTest.script_shell', its value is split into an argument list and used.
  • Otherwise, if the '.qmrc' configuration file contains the common property 'script_shell', its value is split into an argument list and used.
  • Otherwise, the default shell for the target system is used.
Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code
 
_GetShell(self, context)
Return the shell to use to run this test.
source code

Inherited from ExecTestBase: MakeEnvironment, RunProgram, ValidateOutput

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "script", title= "Scrip...
A list of the arguments to the extension class.
  _allow_arg_names_matching_class_vars = 1
True if it is OK for fields to have the same name as class variables.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

Overrides: test.Test.Run

_GetShell(self, context)

source code 

Return the shell to use to run this test.

'context' -- As for 'Test.Run'.

returns -- A sequence of strings giving the path and arguments to be supplied to the shell. The default implementation uses the value of the context property 'ShellScriptTest.script_shell', or, if that is not defined, a platform-specific default.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "script", title= "Script", description= """\
The contents of the shell script.

            Provide the entire shell script here.  The script will be
            written to a temporary file before it is executed.  There
            does not need to be an explicit '#! /path/to/shell' at
            the beginning of the script because QMTest will not direct\
ly
...

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test-module.html0000664000076400007640000000170111122067144024320 0ustar stefanstefan test

Module test



[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.dist.distribution-module.html0000664000076400007640000000213211122067144027021 0ustar stefanstefan distribution

Module distribution


Classes

Distribution

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_database-module.html0000664000076400007640000001177711122067145026316 0ustar stefanstefan qm.test.file_database
Package qm :: Package test :: Module file_database
[hide private]
[frames] | no frames]

Module file_database

source code

Classes [hide private]
  FileDatabase
A 'FileDatabase' stores each test as a single file.
  ExtensionDatabase
An 'ExtensionDatabase' is a 'FileDatabase' where each kind of entity (test, suite, resource) has a particular extension.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.thread_target-pysrc.html0000664000076400007640000036421011122067161027666 0ustar stefanstefan qm.test.classes.thread_target
Package qm :: Package test :: Package classes :: Module thread_target
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.thread_target

  1  ######################################################################## 
  2  # 
  3  # File:   thread_target.py 
  4  # Author: Mark Mitchell 
  5  # Date:   10/30/2001 
  6  # 
  7  # Contents: 
  8  #   QMTest ThreadTarget class. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  from   qm.temporary_directory import TemporaryDirectory 
 21  from   qm.test.base import * 
 22  import qm.test.cmdline 
 23  from   qm.test.command_thread import * 
 24  from   qm.test.target import * 
 25  import Queue 
 26  from   threading import * 
 27   
 28  ######################################################################## 
 29  # classes 
 30  ######################################################################## 
 31   
32 -class LocalThread(CommandThread):
33 """A 'LocalThread' executes commands locally.""" 34
35 - def __init__(self, target):
36 37 CommandThread.__init__(self, target) 38 self.__temporary_directory = TemporaryDirectory()
39 40
41 - def _RunTest(self, descriptor, context):
42 """Run the test given by 'descriptor'. 43 44 'descriptor' -- The name of the test to be run. 45 46 'context' -- The 'Context' in which to run the test.""" 47 48 self.GetTarget()._RunTest(descriptor, context)
49 50
51 - def GetTemporaryDirectory(self):
52 """Return the path to the temporary directory for this thread. 53 54 returns -- The path to the temporary directory associated with 55 this thread.""" 56 57 return self.__temporary_directory.GetPath()
58 59 60
61 -class ThreadTarget(Target):
62 """A target implementation that runs tests in local threads. 63 64 Each thread executes one test or resource at a time.""" 65 66 arguments = [ 67 qm.fields.IntegerField( 68 name="threads", 69 title="Number of Threads", 70 description="""The number of threads to devote to running tests. 71 72 A positive integer that indicates the number of threads to 73 use when running tests. Larger numbers will allow more 74 tests to be run at once. You can experiment with this 75 value to find the number that results in the fastest 76 execution.""", 77 default_value=1), 78 ] 79
80 - def __init__(self, database, properties):
81 """Construct a 'ThreadTarget'. 82 83 'database' -- The 'Database' containing the tests that will be 84 run. 85 86 'properties' -- A dictionary mapping strings (property names) 87 to strings (property values).""" 88 89 # Initialize the base class. 90 Target.__init__(self, database, properties) 91 92 # Create a lock to guard accesses to __ready_threads. 93 self.__ready_threads_lock = Lock() 94 # Create a condition variable to guard accesses to the 95 # available resources table. 96 self.__resources_condition = Condition()
97 98
99 - def IsIdle(self):
100 """Return true if the target is idle. 101 102 returns -- True if the target is idle. If the target is idle, 103 additional tasks may be assigned to it.""" 104 105 # Acquire the lock. (Otherwise, a thread that terminates 106 # right as we are checking for idleness may alter 107 # __ready_threads.) 108 self.__ready_threads_lock.acquire() 109 110 # This target is idle if there are any ready threads. 111 if self.__ready_threads: 112 idle=1 113 else: 114 idle=0 115 116 # Release the lock. 117 self.__ready_threads_lock.release() 118 119 return idle
120 121
122 - def Start(self, response_queue, engine=None):
123 """Start the target. 124 125 'response_queue' -- The 'Queue' in which the results of test 126 executions are placed. 127 128 'engine' -- The 'ExecutionEngine' that is starting the target, 129 or 'None' if this target is being started without an 130 'ExecutionEngine'.""" 131 132 Target.Start(self, response_queue, engine) 133 134 # Build the threads. 135 self.__threads = [] 136 for i in xrange(0, self.threads): 137 # Create the new thread. 138 thread = LocalThread(self) 139 # Start the thread. 140 thread.start() 141 # Remember the thread. 142 self.__threads.append(thread) 143 144 # Initially, all threads are ready. 145 self.__ready_threads = self.__threads[:]
146 147
148 - def Stop(self):
149 """Stop the target. 150 151 postconditions -- The target may no longer be used.""" 152 153 Target.Stop(self) 154 155 # Send each thread a "quit" command. 156 for thread in self.__threads: 157 thread.Stop() 158 # Now wait for each thread process to finish. 159 for thread in self.__threads: 160 thread.join()
161 162
163 - def RunTest(self, descriptor, context):
164 """Run the test given by 'descriptor'. 165 166 'descriptor' -- The 'TestDescriptor' for the test. 167 168 'context' -- The 'Context' in which to run the test. 169 170 Derived classes may override this method.""" 171 172 self._Trace("About to dispatch test " + descriptor.GetId()) 173 174 self.__ready_threads_lock.acquire() 175 176 # The execution engine should never be trying to run a test 177 # when the target is not already idle. 178 assert self.__ready_threads 179 # Pick an idle thread to run the test. 180 thread = self.__ready_threads.pop(0) 181 182 self.__ready_threads_lock.release() 183 184 thread.RunTest(descriptor, context) 185 186 self._Trace("Finished dispatching test " + descriptor.GetId())
187 188
189 - def _RunTest(self, descriptor, context):
190 """Run the test given by 'descriptor'. 191 192 'descriptor' -- The 'TestDescriptor' for the test. 193 194 'context' -- The 'Context' in which to run the test. 195 196 This method will be called from the thread that has been 197 assigned the test.""" 198 199 Target.RunTest(self, descriptor, context)
200 201
202 - def _RecordResult(self, result):
203 """Record the 'result'. 204 205 'result' -- A 'Result' of a test or resource execution.""" 206 207 # If this is a test result, then this thread has finished all 208 # of its work. 209 if result.GetKind() == Result.TEST: 210 self._NoteIdleThread() 211 # Pass the result back to the execution engine. 212 Target._RecordResult(self, result)
213 214
215 - def _BeginResourceSetUp(self, resource_name):
216 """Begin setting up the indicated resource. 217 218 'resource_name' -- A string naming a resource. 219 220 returns -- If the resource has already been set up, returns a 221 tuple '(outcome, map)'. The 'outcome' indicates the outcome 222 that resulted when the resource was set up; the 'map' is a map 223 from strings to strings indicating properties added by this 224 resource. Otherwise, returns 'None', but marks the resource 225 as in the process of being set up; it is the caller's 226 responsibility to finish setting it up by calling 227 '_FinishResourceSetUp'.""" 228 229 # Acquire the lock. 230 self.__resources_condition.acquire() 231 try: 232 # Loop until either we are assigned to set up the resource 233 # or until some other thread has finished setting it up. 234 while 1: 235 rop = Target._BeginResourceSetUp(self, resource_name) 236 # If this is the first thread to call _BeginResourceSetUp 237 # for this thread will set up the resource. 238 if not rop: 239 return rop 240 # If this resource has already been set up, we do not 241 # need to do anything more. 242 if rop[1]: 243 return rop 244 # Otherwise, some other thread is in the process of 245 # setting up this resource so we just wait for it to 246 # finish its job. 247 self.__resources_condition.wait() 248 finally: 249 # Release the lock. 250 self.__resources_condition.release()
251 252
253 - def _FinishResourceSetUp(self, resource, result, properties):
254 255 # Acquire the lock. 256 self.__resources_condition.acquire() 257 # Record the fact that the resource is set up. 258 rop = Target._FinishResourceSetUp(self, resource, result, properties) 259 # Tell all the other threads that the resource has been set 260 # up. 261 self.__resources_condition.notifyAll() 262 # Release the lock. 263 self.__resources_condition.release() 264 265 return rop
266 267
268 - def _NoteIdleThread(self):
269 """Note that the current thread. 270 271 This method is called by the thread when it has completed a 272 task.""" 273 274 # Acquire the lock. (Otherwise, IsIdle might be called right 275 # as we are accessing __ready_threads.) 276 self.__ready_threads_lock.acquire() 277 278 # Now that we have acquired the lock make sure that we release 279 # it, even if an exception occurs. 280 try: 281 thread = currentThread() 282 assert thread not in self.__ready_threads 283 self.__ready_threads.append(thread) 284 finally: 285 # Release the lock. 286 self.__ready_threads_lock.release()
287 288
289 - def _Trace(self, message):
290 """Write a trace 'message'. 291 292 'message' -- A string to be output as a trace message.""" 293 294 if __debug__: 295 tracer = qm.test.cmdline.get_qmtest().GetTracer() 296 tracer.Write(message, "thread_target")
297 298
299 - def _GetTemporaryDirectory(self):
300 301 return currentThread().GetTemporaryDirectory()
302

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_With-module.html0000664000076400007640000000235011122067144031736 0ustar stefanstefan DT_With

Module DT_With


Classes

With

Variables

__rcs_id__

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform_win32-module.html0000664000076400007640000002336211122067145025434 0ustar stefanstefan qm.platform_win32
Package qm :: Module platform_win32
[hide private]
[frames] | no frames]

Module platform_win32

source code

Classes [hide private]
  SignalException
Functions [hide private]
 
get_host_name()
Return the name of this computer.
source code
 
_get_host_name()
Return the name of this computer.
source code
 
open_in_browser(url)
Open a browser window and point it at 'url'.
source code
Variables [hide private]
  default_shell = ['C:\\WINNT\\SYSTEM32\\CMD.EXE']
Function Details [hide private]

open_in_browser(url)

source code 

Open a browser window and point it at 'url'.

The browser is run in a separate, independent process.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.host-module.html0000664000076400007640000001065711122067145023546 0ustar stefanstefan qm.host
Package qm :: Module host
[hide private]
[frames] | no frames]

Module host

source code

Classes [hide private]
  Host
A 'Host' is a logical machine.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.directory_suite-module.html0000664000076400007640000000214711122067144027541 0ustar stefanstefan directory_suite

Module directory_suite


Classes

DirectorySuite

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.host.Host-class.html0000664000076400007640000006013211122067146024274 0ustar stefanstefan qm.host.Host
Package qm :: Module host :: Class Host
[hide private]
[frames] | no frames]

Class Host

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     Host

A 'Host' is a logical machine.

Each logical machine has a default directory. When a file is uploaded to or downloaded from the machine, and a relative path is specified, the patch is relative to the default directory. Similarly, when a program is run on the remote machine, its initial working directory is the default directory.

The interface presented by 'Host' is a lowest common denominator. The objective is not to expose all the functionality of any host; rather it is to provide an interface that can be used on many hosts.

Nested Classes [hide private]
  Executable
An 'Executable' is a simple redirected executable.

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code
 
Run(self, path, arguments, environment=None, timeout=-1, relative=False)
Run a program on the remote host.
source code
 
UploadFile(self, local_file, remote_file=None)
Copy 'local_file' to 'remote_file'.
source code
 
DownloadFile(self, remote_file, local_file)
Copy 'remote_file' to 'local_file'.
source code
 
UploadAndRun(self, path, arguments, environment=None, timeout=-1)
Run a program on the remote host.
source code
 
DeleteFile(self, remote_file)
Delete the 'remote_file'.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  kind = "host"
A string giving kind of extension is implemented by the class.

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

Run(self, path, arguments, environment=None, timeout=-1, relative=False)

source code 

Run a program on the remote host.

'path' -- The name of the program to run, on the remote host. If 'relative' is true, or if 'path' is not an absolute path but does contain at least one directory separator, then 'path' is interpreted relative to the default directory. Otherwise, 'path' is used unmodified.

'arguments' -- The sequence of arguments that should be passed to the program.

'environment' -- If not 'None', a dictionary of pairs of strings to add to the environment of the running program.

'timeout' -- The number of seconds the program is permitted to execute. After the 'timeout' expires, the program will be terminated. However, in some cases (such as when using 'rsh') it will be the local side of the connection that is closed. The remote side of the connection may or may not continue to operate, depending on the vagaries of the remote operating system.

returns -- A pair '(status, output)'. The 'status' is the exit status returned by the program, or 'None' if the exit status is not available. The 'output' is a string giving the combined standard output and standard error output from the program.

UploadFile(self, local_file, remote_file=None)

source code 

Copy 'local_file' to 'remote_file'.

'local_file' -- The name of the file on the local machine.

'remote_file' -- The name of the file on the remote machine. The 'remote_file' must be a relative path. It is interpreted relative to the default directory. If 'None', the 'remote_file' is placed in the default directory using the basename of the 'local_file'.

If the 'local_file' and 'remote_file' are the same, then this function succeeds, but takes no action.

DownloadFile(self, remote_file, local_file)

source code 

Copy 'remote_file' to 'local_file'.

'remote_file' -- The name of the file on the remote machine. The 'remote_file' must be a relative path. It is interpreted relative to the default directory.

'local_file' -- The name of the file on the local machine. If 'None', the 'local_file' is placed in the current directory using the basename of the 'remote_file'.

If the 'local_file' and 'remote_file' are the same, then this function succeeds, but takes no action.

UploadAndRun(self, path, arguments, environment=None, timeout=-1)

source code 

Run a program on the remote host.

'path' -- The name of the program to run, as a path on the local machine.

'arguments' -- As for 'Run'.

'environment' -- As for 'Run'.

'timeout' -- As for 'Run'.

returns -- As for 'Run'.

The program is uploaded to the default directory on the remote host, run, and then deleted.

DeleteFile(self, remote_file)

source code 

Delete the 'remote_file'.

'remote_file' -- A relative path to the file to be deleted.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields-pysrc.html0000664000076400007640000255651111122067157023723 0ustar stefanstefan qm.fields
Package qm :: Module fields
[hide private]
[frames] | no frames]

Source Code for Module qm.fields

   1  ######################################################################## 
   2  # 
   3  # File:   fields.py 
   4  # Author: Alex Samuel 
   5  # Date:   2001-03-05 
   6  # 
   7  # Contents: 
   8  #   General type system for user-defined data constructs. 
   9  # 
  10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
  11  # 
  12  # For license terms see the file COPYING. 
  13  # 
  14  ######################################################################## 
  15   
  16  """A 'Field' determines how data is displayed and stored. 
  17   
  18  A 'Field' is a component of a data structure.  Every 'Field' has a type. 
  19  For example, an 'IntegerField' stores a signed integer while a 
  20  'TextField' stores a string. 
  21   
  22  The value of a 'Field' can be represented as HTML (for display in the 
  23  GUI), or as XML (when written to persistent storage).  Every 'Field' can 
  24  create an HTML form that can be used by the user to update the value of 
  25  the 'Field'. 
  26   
  27  Every 'Extension' class has a set of arguments composed of 'Field'.  An 
  28  instance of that 'Extension' class can be constructed by providing a 
  29  value for each 'Field' object.  The GUI can display the 'Extension' 
  30  object by rendering each of the 'Field' values as HTML.  The user can 
  31  change the value of a 'Field' in the GUI, and then write the 'Extension' 
  32  object to persistent storage. 
  33   
  34  Additional derived classes of 'Field' can be created for use in 
  35  domain-specific situations.  For example, the QMTest 'Test' class 
  36  defines a derived class which allows the user to select from among a set 
  37  of test names.""" 
  38   
  39  ######################################################################## 
  40  # imports 
  41  ######################################################################## 
  42   
  43  import attachment 
  44  import common 
  45  import formatter 
  46  import htmllib 
  47  import os 
  48  import re 
  49  import qm 
  50  import string 
  51  import StringIO 
  52  import structured_text 
  53  import sys 
  54  import time 
  55  import tokenize 
  56  import types 
  57  import urllib 
  58  import web 
  59  import xml.dom 
  60  import xmlutil 
  61   
  62  ######################################################################## 
  63  # classes 
  64  ######################################################################## 
  65   
66 -class Field(object):
67 """A 'Field' is a named, typed component of a data structure.""" 68 69 form_field_prefix = "_field_" 70
71 - def __init__(self, 72 name = "", 73 default_value = None, 74 title = "", 75 description = "", 76 hidden = "false", 77 read_only = "false", 78 computed = "false"):
79 """Create a new (generic) field. 80 81 'name' -- The name of the field. 82 83 'default_value' -- The default value for this field. 84 85 'title' -- The name given this field when it is displayed in 86 user interfaces. 87 88 'description' -- A string explaining the purpose of this field. 89 The 'description' must be provided as structured text. The 90 first line of the structured text must be a one-sentence 91 description of the field; that line is extracted by 92 'GetBriefDescription'. 93 94 'hidden' -- If true, this field is for internal puprpose only 95 and is not shown in user interfaces. 96 97 'read_only' -- If true, this field may not be modified by users. 98 99 'computed' -- If true, this field is computed automatically. 100 All computed fields are implicitly hidden and implicitly 101 read-only. 102 103 The boolean parameters (such as 'hidden') use the convention 104 that true is represented by the string '"true"'; any other value 105 is false. This convention is a historical artifact.""" 106 107 self.__name = name 108 # Use the name as the title, if no other was specified. 109 if not title: 110 self.__title = name 111 else: 112 self.__title = title 113 self.__description = description 114 self.__hidden = hidden == "true" 115 self.__read_only = read_only == "true" 116 self.__computed = computed == "true" 117 118 # All computed fields are also read-only and hidden. 119 if (self.IsComputed()): 120 self.__read_only = 1 121 self.__hidden = 1 122 123 self.__default_value = default_value
124 125
126 - def SetName(self, name):
127 """Set the name of the field.""" 128 129 # We assume that if title==name the title 130 # was not given and so defaulted to name. 131 # Keep it in sync with name in that case. 132 if (self.__name == self.__title): 133 self.__title = name 134 self.__name = name
135 136
137 - def GetName(self):
138 """Return the name of the field.""" 139 140 return self.__name
141 142
143 - def GetDefaultValue(self):
144 """Return the default value for this field.""" 145 146 return common.copy(self.__default_value)
147 148
149 - def GetTitle(self):
150 """Return the user-friendly title of the field.""" 151 152 return self.__title
153 154
155 - def GetDescription(self):
156 """Return a description of this field. 157 158 This description is used when displaying detailed help 159 information about the field.""" 160 161 return self.__description
162 163
164 - def GetBriefDescription(self):
165 """Return a brief description of this field. 166 167 This description is used when prompting for input, or when 168 displaying the current value of the field.""" 169 170 # Get the complete description. 171 description = self.GetDescription() 172 # Return the first paragraph. 173 return structured_text.get_first(description)
174 175
176 - def GetHelp(self):
177 """Generate help text about this field in structured text format.""" 178 179 raise NotImplementedError
180 181
182 - def GetHtmlHelp(self, edit=0):
183 """Generate help text about this field in HTML format. 184 185 'edit' -- If true, display information about editing controls 186 for this field.""" 187 188 description = structured_text.to_html(self.GetDescription()) 189 help = structured_text.to_html(self.GetHelp()) 190 191 return ''' 192 <h3>%s</h3> 193 <h4>About This Field</h4> 194 %s 195 <hr noshade size="2"> 196 <h4>About This Field\'s Values</h4> 197 %s 198 <hr noshade size="2"> 199 <p>Refer to this field as <tt>%s</tt> in Python expressions.</p> 200 ''' % (self.GetTitle(), description, help, self.GetName(), )
201 202
203 - def GetSubfields(self):
204 """Returns the sequence of subfields contained in this field. 205 206 returns -- The sequence of subfields contained in this field. 207 If there are no subfields, an empty sequence is returned.""" 208 209 return ()
210 211
212 - def IsComputed(self):
213 """Returns true if this field is computed automatically. 214 215 returns -- True if this field is computed automatically. A 216 computed field is never displayed to users and is not stored 217 should not be stored; the class containing the field is 218 responsible for recomputing it as necessary.""" 219 220 return self.__computed
221 222
223 - def IsHidden(self):
224 """Returns true if this 'Field' should be hidden from users. 225 226 returns -- True if this 'Field' should be hidden from users. 227 The value of a hidden field is not displayed in the GUI.""" 228 229 return self.__hidden
230 231
232 - def IsReadOnly(self):
233 """Returns true if this 'Field' cannot be modified by users. 234 235 returns -- True if this 'Field' cannot be modified by users. 236 The GUI does not allow users to modify a read-only field.""" 237 238 return self.__read_only
239 240 ### Output methods. 241
242 - def FormatValueAsText(self, value, columns=72):
243 """Return a plain text rendering of a 'value' for this field. 244 245 'columns' -- The maximum width of each line of text. 246 247 returns -- A plain-text string representing 'value'.""" 248 249 # Create a file to hold the result. 250 text_file = StringIO.StringIO() 251 # Format the field as HTML. 252 html_file = StringIO.StringIO(self.FormatValueAsHtml(None, 253 value, 254 "brief")) 255 256 # Turn the HTML into plain text. 257 parser = htmllib.HTMLParser(formatter.AbstractFormatter 258 (formatter.DumbWriter(text_file, 259 maxcol = columns))) 260 parser.feed(html_file) 261 parser.close() 262 text = text_file.getValue() 263 264 # Close the files. 265 html_file.close() 266 text_file.close() 267 268 return text
269 270
271 - def FormatValueAsHtml(self, server, value, style, name=None):
272 """Return an HTML rendering of a 'value' for this field. 273 274 'server' -- The 'WebServer' in which the HTML will be 275 displayed. 276 277 'value' -- The value for this field. May be 'None', which 278 renders a default value (useful for blank forms). 279 280 'style' -- The rendering style. Can be "full" or "brief" (both 281 read-only), or "new" or "edit" or "hidden". 282 283 'name' -- The name to use for the primary HTML form element 284 containing the value of this field, if 'style' specifies the 285 generation of form elements. If 'name' is 'None', the value 286 returned by 'GetHtmlFormFieldName()' should be used. 287 288 returns -- A string containing the HTML representation of 289 'value'.""" 290 291 raise NotImplementedError
292 293
294 - def MakeDomNodeForValue(self, value, document):
295 """Generate a DOM element node for a value of this field. 296 297 'value' -- The value to represent. 298 299 'document' -- The containing DOM document node.""" 300 301 raise NotImplementedError
302 303 ### Input methods. 304
305 - def Validate(self, value):
306 """Validate a field value. 307 308 For an acceptable type and value, return the representation of 309 'value' in the underlying field storage. 310 311 'value' -- A value to validate for this field. 312 313 returns -- If the 'value' is valid, returns 'value' or an 314 equivalent "canonical" version of 'value'. (For example, this 315 function may search a hash table and return an equivalent entry 316 from the hash table.) 317 318 This function must raise an exception if the value is not valid. 319 The string representation of the exception will be used as an 320 error message in some situations. 321 322 Implementations of this method must be idempotent.""" 323 324 raise NotImplementedError
325 326
327 - def ParseTextValue(self, value):
328 """Parse a value represented as a string. 329 330 'value' -- A string representing the value. 331 332 returns -- The corresponding field value. The value returned 333 should be processed by 'Validate' to ensure that it is valid 334 before it is returned.""" 335 336 raise NotImplemented
337 338
339 - def ParseFormValue(self, request, name, attachment_stores):
340 """Convert a value submitted from an HTML form. 341 342 'request' -- The 'WebRequest' containing a value corresponding 343 to this field. 344 345 'name' -- The name corresponding to this field in the 'request'. 346 347 'attachment_stores' -- A dictionary mapping 'AttachmentStore' ids 348 (in the sense of Python's 'id' built-in) to the 349 'AttachmentStore's themselves. 350 351 returns -- A pair '(value, redisplay)'. 'value' is the value 352 for this field, as indicated in 'request'. 'redisplay' is true 353 if and only if the form should be redisplayed, rather than 354 committed. If an error occurs, an exception is thrown.""" 355 356 # Retrieve the value provided in the form. 357 value = request[name] 358 # Treat the result as we would if it were provided on the 359 # command-line. 360 return (self.ParseTextValue(value), 0)
361 362
363 - def GetValueFromDomNode(self, node, attachment_store):
364 """Return a value for this field represented by DOM 'node'. 365 366 This method does not validate the value for this particular 367 instance; it only makes sure the node is well-formed, and 368 returns a value of the correct Python type. 369 370 'node' -- The DOM node that is being evaluated. 371 372 'attachment_store' -- For attachments, the store that should be 373 used. 374 375 If the 'node' is incorrectly formed, this method should raise an 376 exception.""" 377 378 raise NotImplementedError
379 380 # Other methods. 381
382 - def GetHtmlFormFieldName(self):
383 """Return the form field name corresponding this field. 384 385 returns -- A string giving the name that should be used for this 386 field when used in an HTML form.""" 387 388 return self.form_field_prefix + self.GetName()
389 390
391 - def __repr__(self):
392 393 # This output format is more useful when debugging than the 394 # default "<... instance at 0x...>" format provided by Python. 395 return "<%s %s>" % (self.__class__, self.GetName())
396 397 398 ######################################################################## 399
400 -class IntegerField(Field):
401 """An 'IntegerField' stores an 'int' or 'long' object.""" 402
403 - def __init__(self, name="", default_value=0, **properties):
404 """Construct a new 'IntegerField'. 405 406 'name' -- As for 'Field.__init__'. 407 408 'default_value' -- As for 'Field.__init__'. 409 410 'properties' -- Other keyword arguments for 'Field.__init__'.""" 411 412 # Perform base class initialization. 413 super(IntegerField, self).__init__(name, default_value, **properties)
414 415
416 - def GetHelp(self):
417 418 return """This field stores an integer. 419 420 The default value of this field is %d."""
421 422 ### Output methods. 423
424 - def FormatValueAsText(self, value, columns=72):
425 426 return str(value)
427 428
429 - def FormatValueAsHtml(self, server, value, style, name=None):
430 # Use default value if requested. 431 if value is None: 432 value = self.GetDefaultValue() 433 # Use the default field form field name if requested. 434 if name is None: 435 name = self.GetHtmlFormFieldName() 436 437 if style == "new" or style == "edit": 438 return '<input type="text" size="8" name="%s" value="%d" />' \ 439 % (name, value) 440 elif style == "full" or style == "brief": 441 return '<tt>%d</tt>' % value 442 elif style == "hidden": 443 return '<input type="hidden" name="%s" value="%d" />' \ 444 % (name, value) 445 else: 446 assert None
447 448
449 - def MakeDomNodeForValue(self, value, document):
450 return xmlutil.create_dom_text_element(document, "integer", 451 str(value))
452 453 454 ### Input methods. 455
456 - def Validate(self, value):
457 458 if not isinstance(value, (int, long)): 459 raise ValueError, value 460 461 return value
462 463
464 - def ParseTextValue(self, value):
465 466 try: 467 return self.Validate(int(value)) 468 except: 469 raise qm.common.QMException, \ 470 qm.error("invalid integer field value")
471 472
473 - def GetValueFromDomNode(self, node, attachment_store):
474 475 # Make sure 'node' is an '<integer>' element. 476 if node.nodeType != xml.dom.Node.ELEMENT_NODE \ 477 or node.tagName != "integer": 478 raise qm.QMException, \ 479 qm.error("dom wrong tag for field", 480 name=self.GetName(), 481 right_tag="integer", 482 wrong_tag=node.tagName) 483 # Retrieve the contained text. 484 value = xmlutil.get_dom_text(node) 485 # Convert it to an integer. 486 return self.ParseTextValue(value)
487 488 489 ######################################################################## 490
491 -class TextField(Field):
492 """A field that contains text.""" 493
494 - def __init__(self, 495 name = "", 496 default_value = "", 497 multiline = "false", 498 structured = "false", 499 verbatim = "false", 500 not_empty_text = "false", 501 **properties):
502 """Construct a new 'TextField'. 503 504 'multiline' -- If false, a value for this field is a single line 505 of text. If true, multi-line text is allowed. 506 507 'structured' -- If true, the field contains structured text. 508 509 'verbatim' -- If true, the contents of the field are treated as 510 preformatted text. 511 512 'not_empty_text' -- The value of this field is considered 513 invalid if it empty or composed only of whitespace. 514 515 'properties' -- A dictionary of other keyword arguments which 516 are provided to the base class constructor.""" 517 518 # Initialize the base class. 519 super(TextField, self).__init__(name, default_value, **properties) 520 521 self.__multiline = multiline == "true" 522 self.__structured = structured == "true" 523 self.__verbatim = verbatim == "true" 524 self.__not_empty_text = not_empty_text == "true"
525 526
527 - def GetHelp(self):
528 529 help = """ 530 A text field. """ 531 if self.__structured: 532 help = help + ''' 533 The text is interpreted as structured text, and formatted 534 appropriately for the output device. See "Structured Text 535 Formatting 536 Rules":http://www.python.org/sigs/doc-sig/stext.html for 537 more information. ''' 538 elif self.__verbatim: 539 help = help + """ 540 The text is stored verbatim; whitespace and indentation are 541 preserved. """ 542 if self.__not_empty_text: 543 help = help + """ 544 This field may not be empty. """ 545 help = help + """ 546 The default value of this field is "%s". 547 """ % self.GetDefaultValue() 548 return help
549 550 ### Output methods. 551
552 - def FormatValueAsText(self, value, columns=72):
553 554 if self.__structured: 555 return structured_text.to_text(value, width=columns) 556 elif self.__verbatim: 557 return value 558 else: 559 return common.wrap_lines(value, columns)
560 561
562 - def FormatValueAsHtml(self, server, value, style, name=None):
563 564 # Use default value if requested. 565 if value is None: 566 value = "" 567 else: 568 value = str(value) 569 # Use the default field form field name if requested. 570 if name is None: 571 name = self.GetHtmlFormFieldName() 572 573 if style == "new" or style == "edit": 574 if self.__multiline: 575 result = '<textarea cols="64" rows="8" name="%s">' \ 576 '%s</textarea>' \ 577 % (name, web.escape(value)) 578 else: 579 result = \ 580 '<input type="text" size="40" name="%s" value="%s" />' \ 581 % (name, web.escape(value)) 582 # If this is a structured text field, add a note to that 583 # effect, so users aren't surprised. 584 if self.__structured: 585 result = result \ 586 + '<br><font size="-1">This is a ' \ 587 + qm.web.make_help_link_html( 588 qm.structured_text.html_help_text, 589 "structured text") \ 590 + 'field.</font>' 591 return result 592 593 elif style == "hidden": 594 return '<input type="hidden" name="%s" value="%s" />' \ 595 % (name, web.escape(value)) 596 597 elif style == "brief": 598 if self.__structured: 599 # Use only the first line of text. 600 value = string.split(value, "\n", 1) 601 value = web.format_structured_text(value[0]) 602 else: 603 # Replace all whitespace with ordinary space. 604 value = re.sub(r"\s", " ", value) 605 606 # Truncate to 80 characters, if it's longer. 607 if len(value) > 80: 608 value = value[:80] + "..." 609 610 if self.__verbatim: 611 # Put verbatim text in a <tt> element. 612 return '<tt>%s</tt>' % web.escape(value) 613 elif self.__structured: 614 # It's already formatted as HTML; don't escape it. 615 return value 616 else: 617 # Other text set normally. 618 return web.escape(value) 619 620 elif style == "full": 621 if self.__verbatim: 622 # Wrap lines before escaping special characters for 623 # HTML. Use a special tag to indicate line breaks. If 624 # we were to escape first, line lengths would be 625 # computed using escape codes rather than visual 626 # characters. 627 break_delimiter = "#@LINE$BREAK@#" 628 value = common.wrap_lines(value, columns=80, 629 break_delimiter=break_delimiter) 630 # Now escape special characters. 631 value = web.escape(value) 632 # Replace the line break tag with visual indication of 633 # the break. 634 value = string.replace(value, 635 break_delimiter, r"<blink>\</blink>") 636 # Place verbatim text in a <pre> element. 637 return '<pre>%s</pre>' % value 638 elif self.__structured: 639 return web.format_structured_text(value) 640 else: 641 if value == "": 642 # Browsers don't deal nicely with empty table cells, 643 # so put an extra space here. 644 return "&nbsp;" 645 else: 646 return web.escape(value) 647 648 else: 649 raise ValueError, style
650 651
652 - def MakeDomNodeForValue(self, value, document):
653 654 return xmlutil.create_dom_text_element(document, "text", value)
655 656 ### Input methods. 657
658 - def Validate(self, value):
659 660 if not isinstance(value, types.StringTypes): 661 raise ValueError, value 662 663 # Clean up unless it's a verbatim string. 664 if not self.__verbatim: 665 # Remove leading whitespace. 666 value = string.lstrip(value) 667 # If this field has the not_empty_text property set, make sure the 668 # value complies. 669 if self.__not_empty_text and value == "": 670 raise ValueError, \ 671 qm.error("empty text field value", 672 field_title=self.GetTitle()) 673 # If this is not a multi-line text field, remove line breaks 674 # (and surrounding whitespace). 675 if not self.__multiline: 676 value = re.sub(" *\n+ *", " ", value) 677 return value
678 679
680 - def ParseFormValue(self, request, name, attachment_stores):
681 682 # HTTP specifies text encodings are CR/LF delimited; convert to 683 # the One True Text Format (TM). 684 return (self.ParseTextValue(qm.convert_from_dos_text(request[name])), 685 0)
686 687
688 - def ParseTextValue(self, value):
689 690 return self.Validate(value)
691 692
693 - def GetValueFromDomNode(self, node, attachment_store):
694 695 # Make sure 'node' is a '<text>' element. 696 if node.nodeType != xml.dom.Node.ELEMENT_NODE \ 697 or node.tagName != "text": 698 raise qm.QMException, \ 699 qm.error("dom wrong tag for field", 700 name=self.GetName(), 701 right_tag="text", 702 wrong_tag=node.tagName) 703 return self.Validate(xmlutil.get_dom_text(node))
704 705 706 ######################################################################## 707
708 -class TupleField(Field):
709 """A 'TupleField' contains zero or more other 'Field' objects. 710 711 The contained 'Field' objects may have different types. The value 712 of a 'TupleField' is a Python list; the values in the list 713 correspond to the values of the contained 'Field' objects. For 714 example, '["abc", 3]' would be a valid value for a 'TupleField' 715 containing a 'TextField' and an 'IntegerField'.""" 716
717 - def __init__(self, name = "", fields = None, **properties):
718 """Construct a new 'TupleField'. 719 720 'name' -- The name of the field. 721 722 'fields' -- A sequence of 'Field' instances. 723 724 The new 'TupleField' stores a list whose elements correspond to 725 the 'fields'.""" 726 727 self.__fields = fields == None and [] or fields 728 default_value = map(lambda f: f.GetDefaultValue(), self.__fields) 729 Field.__init__(self, name, default_value, **properties)
730 731
732 - def GetHelp(self):
733 734 help = "" 735 need_space = 0 736 for f in self.__fields: 737 if need_space: 738 help += "\n" 739 else: 740 need_space = 1 741 help += "** " + f.GetTitle() + " **\n\n" 742 help += f.GetHelp() 743 744 return help
745 746
747 - def GetSubfields(self):
748 749 return self.__fields
750 751 752 ### Output methods. 753
754 - def FormatValueAsHtml(self, server, value, style, name = None):
755 756 # Use the default name if none is specified. 757 if name is None: 758 name = self.GetHtmlFormFieldName() 759 760 # Format the field as a multi-column table. 761 html = '<table border="0" cellpadding="0">\n <tr>\n' 762 for f, v in map(None, self.__fields, value): 763 element_name = name + "_" + f.GetName() 764 html += " <td><b>" + f.GetTitle() + "</b>:</td>\n" 765 html += (" <td>\n" 766 + f.FormatValueAsHtml(server, v, style, element_name) 767 + " </td>\n") 768 html += " </tr>\n</table>\n" 769 770 return html
771 772
773 - def MakeDomNodeForValue(self, value, document):
774 775 element = document.createElement("tuple") 776 for f, v in map(None, self.__fields, value): 777 element.appendChild(f.MakeDomNodeForValue(v, document)) 778 779 return element
780 781 ### Input methods. 782
783 - def Validate(self, value):
784 785 assert len(value) == len(self.__fields) 786 return map(lambda f, v: f.Validate(v), 787 self.__fields, value)
788 789
790 - def ParseFormValue(self, request, name, attachment_stores):
791 792 value = [] 793 redisplay = 0 794 for f in self.__fields: 795 v, r = f.ParseFormValue(request, name + "_" + f.GetName(), 796 attachment_stores) 797 value.append(v) 798 if r: 799 redisplay = 1 800 801 # Now that we've computed the value of the entire tuple, make 802 # sure it is valid. 803 value = self.Validate(value) 804 805 return (value, redisplay)
806 807
808 - def GetValueFromDomNode(self, node, attachment_store):
809 810 values = [] 811 for f, element in map(None, self.__fields, node.childNodes): 812 values.append(f.GetValueFromDomNode(element, attachment_store)) 813 814 return self.Validate(values)
815 816 817
818 -class DictionaryField(Field):
819 """A 'DictionaryField' maps keys to values.""" 820
821 - def __init__(self, key_field, value_field, **properties):
822 """Construct a new 'DictionaryField'. 823 824 'key_field' -- The key field. 825 826 'value_field' -- The value field. 827 """ 828 829 self.__key_field = key_field 830 self.__value_field = value_field 831 super(DictionaryField, self).__init__(**properties)
832 833
834 - def GetHelp(self):
835 836 help = """ 837 A dictionary field. A dictionary maps keys to values. The key type: 838 %s 839 The value type: 840 %s"""%(self.__key_field.GetHelp(), self.__value_field.GetHelp()) 841 return help
842 843
844 - def GetKeyField(self): return self.__key_field
845 - def GetValueField(self): return self.__value_field
846 847 ### Output methods. 848
849 - def FormatValueAsHtml(self, server, content, style, name = None):
850 851 if content is None: 852 content = {} 853 # Use the default name if none is specified. 854 if name is None: 855 name = self.GetHtmlFormFieldName() 856 857 if style == 'brief' or style == 'full': 858 if len(content) == 0: 859 # An empty set. 860 return 'None' 861 body = ['<th>%s</th><td>%s</td>\n' 862 %(self.__key_field.FormatValueAsHtml(server, key, style), 863 self.__value_field.FormatValueAsHtml(server, value, style)) 864 for (key, value) in content.iteritems()] 865 return '<table><tr>%s</tr>\n</table>\n'%'</tr>\n<tr>'.join(body) 866 867 elif style in ['new', 'edit', 'hidden']: 868 html = '' 869 if content: 870 # Create a table to represent the dictionary -- but only if it is 871 # non-empty. A table with no body is invalid HTML. 872 html += ('<table border="0" cellpadding="0" cellspacing="0">' 873 '\n <tbody>\n') 874 element_number = 0 875 for key, value in content.iteritems(): 876 html += ' <tr>\n <td>' 877 element_name = name + '_%d' % element_number 878 checkbox_name = element_name + "_remove" 879 if style == 'edit': 880 html += ('<input type="checkbox" name="%s" /></td>\n' 881 ' <td>\n' 882 % checkbox_name) 883 element_name = name + '_key_%d' % element_number 884 html += (' <th>%s</th>\n' 885 %self.__key_field.FormatValueAsHtml(server, key, 886 style, 887 element_name)) 888 element_name = name + '_value_%d' % element_number 889 html += (' <td>%s</td>\n' 890 %self.__value_field.FormatValueAsHtml(server, value, 891 style, 892 element_name)) 893 html += ' </tr>\n' 894 element_number += 1 895 html += ' </tbody>\n</table>\n' 896 # The action field is used to keep track of whether the 897 # "Add" or "Remove" button has been pushed. It would be 898 # much nice if we could use JavaScript to update the 899 # table, but Netscape 4, and even Mozilla 1.0, do not 900 # permit that. Therefore, we have to go back to the server. 901 html += '<input type="hidden" name="%s" value="" />' % name 902 html += ('<input type="hidden" name="%s_count" value="%d" />' 903 % (name, len(content))) 904 if style != 'hidden': 905 html += ('<table border="0" cellpadding="0" cellspacing="0">\n' 906 ' <tbody>\n' 907 ' <tr>\n' 908 ' <td><input type="button" name="%s_add" ' 909 'value="Add Another" ' 910 '''onclick="%s.value = 'add'; submit();" />''' 911 '</td>\n' 912 ' <td><input type="button" name="%s_remove"' 913 'value="Remove Selected" ' 914 '''onclick="%s.value = 'remove'; submit();" />''' 915 '</td>\n' 916 ' </tr>' 917 ' </tbody>' 918 '</table>' 919 % (name, name, name, name)) 920 return html
921 922
923 - def MakeDomNodeForValue(self, value, document):
924 925 element = document.createElement('dictionary') 926 for k, v in value.iteritems(): 927 item = element.appendChild(document.createElement('item')) 928 item.appendChild(self.__key_field.MakeDomNodeForValue(k, document)) 929 item.appendChild(self.__value_field.MakeDomNodeForValue(v, document)) 930 return element
931 932 933 ### Input methods. 934
935 - def Validate(self, value):
936 937 valid = {} 938 for k, v in value.items(): 939 valid[self.__key_field.Validate(k)] = self.__value_field.Validate(v) 940 941 return valid
942 943
944 - def ParseTextValue(self, value):
945 946 raise NotImplementedError
947 948
949 - def ParseFormValue(self, request, name, attachment_stores):
950 951 content = {} 952 redisplay = 0 953 954 action = request[name] 955 956 for i in xrange(int(request[name + '_count'])): 957 if not (action == 'remove' 958 and request.get(name + '_%d_remove'%i) == 'on'): 959 key, rk = self.__key_field.ParseFormValue(request, 960 name + '_key_%d'%i, 961 attachment_stores) 962 value, rv = self.__value_field.ParseFormValue(request, 963 name + '_value_%d'%i, 964 attachment_stores) 965 content[key] = value 966 if rk or rv: 967 redisplay = 1 968 969 # Remove entries from the request that might cause confusion 970 # when the page is redisplayed. 971 names = [] 972 for n, v in request.items(): 973 if n[:len(name)] == name: 974 names.append(n) 975 for n in names: 976 del request[n] 977 978 content = self.Validate(content) 979 980 if action == 'add': 981 redisplay = 1 982 content[self.__key_field.GetDefaultValue()] =\ 983 self.__value_field.GetDefaultValue() 984 elif action == 'remove': 985 redisplay = 1 986 987 return (content, redisplay)
988 989
990 - def GetValueFromDomNode(self, node, attachment_store):
991 992 values = {} 993 for item in node.childNodes: 994 if item.nodeType == xml.dom.Node.ELEMENT_NODE: 995 values[self.__key_field.GetValueFromDomNode 996 (item.childNodes[0], attachment_store)] =\ 997 self.__value_field.GetValueFromDomNode(item.childNodes[1], 998 attachment_store) 999 return self.Validate(values)
1000 1001 1002
1003 -class SetField(Field):
1004 """A field containing zero or more instances of some other field. 1005 1006 All contents must be of the same field type. A set field may not 1007 contain sets. 1008 1009 The default field value is set to an empty set.""" 1010
1011 - def __init__(self, contained, not_empty_set = "false", default_value = None, 1012 **properties):
1013 """Create a set field. 1014 1015 The name of the contained field is taken as the name of this 1016 field. 1017 1018 'contained' -- An 'Field' instance describing the 1019 elements of the set. 1020 1021 'not_empty_set' -- If true, this field may not be empty, 1022 i.e. the value of this field must contain at least one element. 1023 1024 raises -- 'ValueError' if 'contained' is a set field. 1025 1026 raises -- 'TypeError' if 'contained' is not a 'Field'.""" 1027 1028 if not properties.has_key('description'): 1029 properties['description'] = contained.GetDescription() 1030 1031 super(SetField, self).__init__( 1032 contained.GetName(), 1033 default_value or [], 1034 title = contained.GetTitle(), 1035 **properties) 1036 1037 # A set field may not contain a set field. 1038 if isinstance(contained, SetField): 1039 raise ValueError, \ 1040 "A set field may not contain a set field." 1041 if not isinstance(contained, Field): 1042 raise TypeError, "A set must contain another field." 1043 # Remeber the contained field type. 1044 self.__contained = contained 1045 self.__not_empty_set = not_empty_set == "true"
1046 1047
1048 - def GetHelp(self):
1049 return """ 1050 A set field. A set contains zero or more elements, all of the 1051 same type. The elements of the set are described below: 1052 1053 """ + self.__contained.GetHelp()
1054 1055
1056 - def GetSubfields(self):
1057 1058 return (self.__contained,)
1059 1060
1061 - def GetHtmlHelp(self, edit=0):
1062 help = Field.GetHtmlHelp(self) 1063 if edit: 1064 # In addition to the standard generated help, include 1065 # additional instructions about using the HTML controls. 1066 help = help + """ 1067 <hr noshade size="2"> 1068 <h4>Modifying This Field</h4> 1069 1070 <p>Add a new element to the set by clicking the 1071 <i>Add</i> button. The new element will have a default 1072 value until you change it. To remove elements from the 1073 set, select them by checking the boxes on the left side of 1074 the form. Then, click the <i>Remove</i> button.</p> 1075 """ 1076 return help
1077 1078 ### Output methods. 1079
1080 - def FormatValueAsText(self, value, columns=72):
1081 # If the set is empty, indicate this specially. 1082 if len(value) == 0: 1083 return "None" 1084 # Format each element of the set, and join them into a 1085 # comma-separated list. 1086 contained_field = self.__contained 1087 formatted_items = [] 1088 for item in value: 1089 formatted_item = contained_field.FormatValueAsText(item, columns) 1090 formatted_items.append(repr(formatted_item)) 1091 result = "[ " + string.join(formatted_items, ", ") + " ]" 1092 return qm.common.wrap_lines(result, columns)
1093 1094
1095 - def FormatValueAsHtml(self, server, value, style, name=None):
1096 # Use default value if requested. 1097 if value is None: 1098 value = [] 1099 # Use the default field form field name if requested. 1100 if name is None: 1101 name = self.GetHtmlFormFieldName() 1102 1103 contained_field = self.__contained 1104 if style == "brief" or style == "full": 1105 if len(value) == 0: 1106 # An empty set. 1107 return "None" 1108 formatted \ 1109 = map(lambda v: contained_field.FormatValueAsHtml(server, 1110 v, style), 1111 value) 1112 if style == "brief": 1113 # In the brief style, list elements separated by commas. 1114 separator = ", " 1115 else: 1116 # In the full style, list elements one per line. 1117 separator = "<br>\n" 1118 return string.join(formatted, separator) 1119 1120 elif style in ["new", "edit", "hidden"]: 1121 html = "" 1122 if value: 1123 # Create a table to represent the set -- but only if the set is 1124 # non-empty. A table with no body is invalid HTML. 1125 html += ('<table border="0" cellpadding="0" cellspacing="0">' 1126 "\n <tbody>\n") 1127 element_number = 0 1128 for element in value: 1129 html += " <tr>\n <td>" 1130 element_name = name + "_%d" % element_number 1131 checkbox_name = element_name + "_remove" 1132 if style == "edit": 1133 html += \ 1134 ('<input type="checkbox" name="%s" /></td>\n' 1135 ' <td>\n' 1136 % checkbox_name) 1137 html += contained_field.FormatValueAsHtml(server, 1138 element, 1139 style, 1140 element_name) 1141 html += " </td>\n </tr>\n" 1142 element_number += 1 1143 html += " </tbody>\n</table>\n" 1144 # The action field is used to keep track of whether the 1145 # "Add" or "Remove" button has been pushed. It would be 1146 # much nice if we could use JavaScript to update the 1147 # table, but Netscape 4, and even Mozilla 1.0, do not 1148 # permit that. Therefore, we have to go back to the server. 1149 html += '<input type="hidden" name="%s" value="" />' % name 1150 html += ('<input type="hidden" name="%s_count" value="%d" />' 1151 % (name, len(value))) 1152 if style != "hidden": 1153 html += ('<table border="0" cellpadding="0" cellspacing="0">\n' 1154 ' <tbody>\n' 1155 ' <tr>\n' 1156 ' <td><input type="button" name="%s_add" ' 1157 'value="Add Another" ' 1158 '''onclick="%s.value = 'add'; submit();" />''' 1159 '</td>\n' 1160 ' <td><input type="button" name="%s_remove"' 1161 'value="Remove Selected" ' 1162 '''onclick="%s.value = 'remove'; submit();" />''' 1163 '</td>\n' 1164 ' </tr>' 1165 ' </tbody>' 1166 '</table>' 1167 % (name, name, name, name)) 1168 return html
1169 1170
1171 - def MakeDomNodeForValue(self, value, document):
1172 1173 # Create a set element. 1174 element = document.createElement("set") 1175 # Add a child node for each item in the set. 1176 contained_field = self.__contained 1177 for item in value: 1178 # The contained field knows how to make a DOM node for each 1179 # item in the set. 1180 item_node = contained_field.MakeDomNodeForValue(item, document) 1181 element.appendChild(item_node) 1182 return element
1183 1184 ### Input methods. 1185
1186 - def Validate(self, value):
1187 1188 # If this field has the not_empty_set property set, make sure 1189 # the value complies. 1190 if self.__not_empty_set and len(value) == 0: 1191 raise ValueError, \ 1192 qm.error("empty set field value", 1193 field_title=self.GetTitle()) 1194 # Assume 'value' is a sequence. Copy it, simultaneously 1195 # validating each element in the contained field. 1196 return map(lambda v: self.__contained.Validate(v), 1197 value)
1198 1199
1200 - def ParseTextValue(self, value):
1201 1202 def invalid(tok): 1203 """Raise an exception indicating a problem with 'value'. 1204 1205 'tok' -- A token indicating the position of the problem. 1206 1207 This function does not return; instead, it raises an 1208 appropriate exception.""" 1209 1210 raise qm.QMException, \ 1211 qm.error("invalid set value", start = value[tok[2][1]:])
1212 1213 # Use the Python parser to handle the elements of the set. 1214 s = StringIO.StringIO(value) 1215 g = tokenize.generate_tokens(s.readline) 1216 1217 # Read the opening square bracket. 1218 tok = g.next() 1219 if tok[0] != tokenize.OP or tok[1] != "[": 1220 invalid(tok) 1221 1222 # There are no elements yet. 1223 elements = [] 1224 1225 # Keep going until we find the closing bracket. 1226 while 1: 1227 # If we've reached the closing bracket, the set is 1228 # complete. 1229 tok = g.next() 1230 if tok[0] == tokenize.OP and tok[1] == "]": 1231 break 1232 # If this is not the first element of the set, there should 1233 # be a comma before the next element. 1234 if elements: 1235 if tok[0] != tokenize.OP or tok[1] != ",": 1236 invalid(tok) 1237 tok = g.next() 1238 # The next token should be a string constant. 1239 if tok[0] != tokenize.STRING: 1240 invalid(tok) 1241 # Parse the string constant. 1242 v = eval(tok[1]) 1243 elements.append(self.__contained.ParseTextValue(v)) 1244 1245 # There should not be any tokens left over. 1246 tok = g.next() 1247 if not tokenize.ISEOF(tok[0]): 1248 invalid(tok) 1249 1250 return self.Validate(elements)
1251 1252
1253 - def ParseFormValue(self, request, name, attachment_stores):
1254 1255 values = [] 1256 redisplay = 0 1257 1258 # See if the user wants to add or remove elements from the set. 1259 action = request[name] 1260 # Loop over the entries for each of the elements, adding them to 1261 # the set. 1262 contained_field = self.__contained 1263 element = 0 1264 for element in xrange(int(request[name + "_count"])): 1265 element_name = name + "_%d" % element 1266 if not (action == "remove" 1267 and request.get(element_name + "_remove") == "on"): 1268 v, r = contained_field.ParseFormValue(request, 1269 element_name, 1270 attachment_stores) 1271 values.append(v) 1272 if r: 1273 redisplay = 1 1274 element += 1 1275 1276 # Remove entries from the request that might cause confusion 1277 # when the page is redisplayed. 1278 names = [] 1279 for n, v in request.items(): 1280 if n[:len(name)] == name: 1281 names.append(n) 1282 for n in names: 1283 del request[n] 1284 1285 # Validate the values. 1286 values = self.Validate(values) 1287 1288 # If the user requested another element, add to the set. 1289 if action == "add": 1290 redisplay = 1 1291 # There's no need to validate this new value and it may in 1292 # fact be dangerous to do so. For example, the default 1293 # value for a ChoiceField might be the "nothing selected" 1294 # value, which is not a valid selection. If the user does 1295 # not actually select something, the problem will be 1296 # reported when the form is submitted. 1297 values.append(contained_field.GetDefaultValue()) 1298 elif action == "remove": 1299 redisplay = 1 1300 1301 return (values, redisplay)
1302 1303
1304 - def GetValueFromDomNode(self, node, attachment_store):
1305 # Make sure 'node' is a '<set>' element. 1306 if node.nodeType != xml.dom.Node.ELEMENT_NODE \ 1307 or node.tagName != "set": 1308 raise qm.QMException, \ 1309 qm.error("dom wrong tag for field", 1310 name=self.GetName(), 1311 right_tag="set", 1312 wrong_tag=node.tagName) 1313 # Use the contained field to extract values for the children of 1314 # this node, which are the set elements. 1315 contained_field = self.__contained 1316 fn = lambda n, f=contained_field, s=attachment_store: \ 1317 f.GetValueFromDomNode(n, s) 1318 values = map(fn, 1319 filter(lambda n: n.nodeType == xml.dom.Node.ELEMENT_NODE, 1320 node.childNodes)) 1321 return self.Validate(values)
1322 1323 1324 1325 ######################################################################## 1326
1327 -class UploadAttachmentPage(web.DtmlPage):
1328 """DTML context for generating upload-attachment.dtml.""" 1329
1330 - def __init__(self, 1331 attachment_store, 1332 field_name, 1333 encoding_name, 1334 summary_field_name, 1335 in_set=0):
1336 """Create a new page object. 1337 1338 'attachment_store' -- The AttachmentStore in which the new 1339 attachment will be placed. 1340 1341 'field_name' -- The user-visible name of the field for which an 1342 attachment is being uploaded. 1343 1344 'encoding_name' -- The name of the HTML input that should 1345 contain the encoded attachment. 1346 1347 'summary_field_name' -- The name of the HTML input that should 1348 contain the user-visible summary of the attachment. 1349 1350 'in_set' -- If true, the attachment is being added to an 1351 attachment set field.""" 1352 1353 web.DtmlPage.__init__(self, "attachment.dtml") 1354 # Use a brand-new location for the attachment data. 1355 self.location = attachment.make_temporary_location() 1356 # Set up properties. 1357 self.attachment_store_id = id(attachment_store) 1358 self.field_name = field_name 1359 self.encoding_name = encoding_name 1360 self.summary_field_name = summary_field_name 1361 self.in_set = in_set
1362 1363
1364 - def MakeSubmitUrl(self):
1365 """Return the URL for submitting this form.""" 1366 1367 return self.request.copy(AttachmentField.upload_url).AsUrl()
1368 1369 1370
1371 -class AttachmentField(Field):
1372 """A field containing a file attachment. 1373 1374 Note that the 'FormatValueAsHtml' method uses a popup upload form 1375 for uploading new attachment. The web server must be configured to 1376 handle the attachment submission requests. See 1377 'attachment.register_attachment_upload_script'.""" 1378 1379 upload_url = "/attachment-upload" 1380 """The URL used to upload data for an attachment. 1381 1382 The upload request will include these query arguments: 1383 1384 'location' -- The location at which to store the attachment data. 1385 1386 'file_data' -- The attachment data. 1387 1388 """ 1389 1390 download_url = "/attachment-download" 1391 """The URL used to download an attachment. 1392 1393 The download request will include this query argument: 1394 1395 'location' -- The location in the attachment store from which to 1396 retrieve the attachment data. 1397 1398 """ 1399 1400
1401 - def __init__(self, name = "", **properties):
1402 """Create an attachment field. 1403 1404 Sets the default value of the field to 'None'.""" 1405 1406 # Perform base class initialization. 1407 apply(Field.__init__, (self, name, None), properties)
1408 1409
1410 - def GetHelp(self):
1411 return """ 1412 An attachment field. An attachment consists of an uploaded 1413 file, which may be of any file type, plus a short description. 1414 The name of the file, as well as the file's MIME type, are also 1415 stored. The description is a single line of plain text. 1416 1417 An attachment need not be provided. The field may be left 1418 empty."""
1419 1420
1421 - def GetHtmlHelp(self, edit=0):
1422 help = Field.GetHtmlHelp(self) 1423 if edit: 1424 # In addition to the standard generated help, include 1425 # additional instructions about using the HTML controls. 1426 help = help + """ 1427 <hr noshade size="2"> 1428 <h4>Modifying This Field</h4> 1429 1430 <p>The text control describes the current value of this 1431 field, displaying the attachment's description, file name, 1432 and MIME type. If the field is empty, the text control 1433 displays "None". The text control cannot be edited.</p> 1434 1435 <p>To upload a new attachment (replacing the previous one, 1436 if any), click on the <i>Change...</i> button. To clear the 1437 current attachment and make the field empty, click on the 1438 <i>Clear</i> button.</p> 1439 """ 1440 return help
1441 1442 ### Output methods. 1443
1444 - def FormatValueAsText(self, value, columns=72):
1445 1446 return self._FormatSummary(value)
1447 1448
1449 - def FormatValueAsHtml(self, server, value, style, name=None):
1450 1451 field_name = self.GetName() 1452 1453 if value is None: 1454 # The attachment field value may be 'None', indicating no 1455 # attachment. 1456 pass 1457 elif isinstance(value, attachment.Attachment): 1458 location = value.GetLocation() 1459 mime_type = value.GetMimeType() 1460 description = value.GetDescription() 1461 file_name = value.GetFileName() 1462 else: 1463 raise ValueError, "'value' must be 'None' or an 'Attachment'" 1464 1465 # Use the default field form field name if requested. 1466 if name is None: 1467 name = self.GetHtmlFormFieldName() 1468 1469 if style == "full" or style == "brief": 1470 if value is None: 1471 return "None" 1472 # Link the attachment description to the data itself. 1473 download_url = web.WebRequest(self.download_url, 1474 location=location, 1475 mime_type=mime_type).AsUrl() 1476 # Here's a nice hack. If the user saves the attachment to a 1477 # file, browsers (some at least) guess the default file name 1478 # from the URL by taking everything following the final 1479 # slash character. So, we add this bogus-looking argument 1480 # to fool the browser into using our file name. 1481 download_url = download_url + \ 1482 "&=/" + urllib.quote_plus(file_name) 1483 1484 result = '<a href="%s">%s</a>' \ 1485 % (download_url, description) 1486 # For the full style, display the MIME type. 1487 if style == "full": 1488 result = result + ' (%s)' % (mime_type) 1489 return result 1490 1491 elif style == "new" or style == "edit": 1492 1493 # Some trickiness here. 1494 # 1495 # For attachment fields, the user specifies the file to 1496 # upload via a popup form, which is shown in a new browser 1497 # window. When that form is submitted, the attachment data 1498 # is immediately uploaded to the server. 1499 # 1500 # The information that's stored for an attachment is made of 1501 # four parts: a description, a MIME type, the file name, and 1502 # the location of the data itself. The user enters these 1503 # values in the popup form, which sets a hidden field on 1504 # this form to an encoding of that information. 1505 # 1506 # Also, when the popup form is submitted, the attachment 1507 # data is uploaded. By the time this form is submitted, the 1508 # attachment data should be uploaded already. The uploaded 1509 # attachment data is stored in the temporary attachment 1510 # area; it's copied into the IDB when the issue revision is 1511 # submitted. 1512 1513 summary_field_name = "_attachment" + name 1514 1515 # Fill in the description if there's already an attachment. 1516 summary_value = 'value="%s"' % self._FormatSummary(value) 1517 if value is None: 1518 field_value = "" 1519 else: 1520 # We'll encode all the relevant information. 1521 parts = (description, mime_type, location, file_name, 1522 str(id(value.GetStore()))) 1523 # Each part is URL-encoded. 1524 parts = map(urllib.quote, parts) 1525 # The parts are joined into a semicolon-delimited list. 1526 field_value = string.join(parts, ";") 1527 field_value = 'value="%s"' % field_value 1528 1529 # Generate the popup upload page. 1530 upload_page = \ 1531 UploadAttachmentPage(server.GetTemporaryAttachmentStore(), 1532 self.GetTitle(), 1533 name, 1534 summary_field_name)() 1535 1536 # Generate controls for this form. 1537 1538 # A text control for the user-visible summary of the 1539 # attachment. The "readonly" property isn't supported in 1540 # Netscape, so prevent the user from typing into the form by 1541 # forcing focus away from the control. 1542 text_control = ''' 1543 <input type="text" 1544 readonly 1545 size="40" 1546 name="%s" 1547 onfocus="this.blur();" 1548 %s>''' % (summary_field_name, summary_value) 1549 # A button to pop up the upload form. It causes the upload 1550 # page to appear in a popup window. 1551 upload_button \ 1552 = server.MakeButtonForCachedPopup("Upload", 1553 upload_page, 1554 window_width=640, 1555 window_height=320) 1556 # A button to clear the attachment. 1557 clear_button = ''' 1558 <input type="button" 1559 size="20" 1560 value=" Clear " 1561 name="_clear_%s" 1562 onclick="document.form.%s.value = 'None'; 1563 document.form.%s.value = '';" /> 1564 ''' % (field_name, summary_field_name, name) 1565 # A hidden control for the encoded attachment value. The 1566 # popup upload form fills in this control. 1567 hidden_control = ''' 1568 <input type="hidden" 1569 name="%s" 1570 %s>''' % (name, field_value) 1571 # Now assemble the controls with some layout bits. 1572 result = ''' 1573 %s%s<br> 1574 %s%s 1575 ''' % (text_control, hidden_control, upload_button, clear_button) 1576 1577 return result 1578 1579 else: 1580 raise ValueError, style
1581 1582
1583 - def MakeDomNodeForValue(self, value, document):
1584 return attachment.make_dom_node(value, document)
1585 1586
1587 - def _FormatSummary(self, attachment):
1588 """Generate a user-friendly summary for 'attachment'. 1589 1590 This value is used when generating the form. It can't be 1591 editied.""" 1592 1593 if attachment is None: 1594 return "None" 1595 else: 1596 return "%s (%s; %s)" \ 1597 % (attachment.GetDescription(), 1598 attachment.GetFileName(), 1599 attachment.GetMimeType())
1600 1601 1602 ### Input methods. 1603
1604 - def Validate(self, value):
1605 1606 # The value should be an instance of 'Attachment', or 'None'. 1607 if value != None and not isinstance(value, attachment.Attachment): 1608 raise ValueError, \ 1609 "the value of an attachment field must be an 'Attachment'" 1610 return value
1611 1612
1613 - def ParseFormValue(self, request, name, attachment_stores):
1614 1615 encoding = request[name] 1616 # An empty string represnts a missing attachment, which is OK. 1617 if string.strip(encoding) == "": 1618 return None 1619 # The encoding is a semicolon-separated sequence indicating the 1620 # relevant information about the attachment. 1621 parts = string.split(encoding, ";") 1622 # Undo the URL encoding of each component. 1623 parts = map(urllib.unquote, parts) 1624 # Unpack the results. 1625 description, mime_type, location, file_name, store_id = parts 1626 # Figure out which AttachmentStore corresponds to the id 1627 # provided. 1628 store = attachment_stores[int(store_id)] 1629 # Create the attachment. 1630 value = attachment.Attachment(mime_type, description, 1631 file_name, location, 1632 store) 1633 return (self.Validate(value), 0)
1634 1635
1636 - def GetValueFromDomNode(self, node, attachment_store):
1637 1638 # Make sure 'node' is an "attachment" element. 1639 if node.nodeType != xml.dom.Node.ELEMENT_NODE \ 1640 or node.tagName != "attachment": 1641 raise qm.QMException, \ 1642 qm.error("dom wrong tag for field", 1643 name=self.GetName(), 1644 right_tag="attachment", 1645 wrong_tag=node.tagName) 1646 return self.Validate(attachment.from_dom_node(node, attachment_store))
1647 1648 1649 ######################################################################## 1650
1651 -class ChoiceField(TextField):
1652 """A 'ChoiceField' allows choosing one of several values. 1653 1654 The set of acceptable values can be determined when the field is 1655 created or dynamically. The empty string is used as the "no 1656 choice" value, and cannot therefore be one of the permitted 1657 values.""" 1658
1659 - def GetItems(self):
1660 """Return the options from which to choose. 1661 1662 returns -- A sequence of strings, each of which will be 1663 presented as a choice for the user.""" 1664 1665 raise NotImplementedError
1666 1667
1668 - def FormatValueAsHtml(self, server, value, style, name = None):
1669 1670 if style not in ("new", "edit"): 1671 return qm.fields.TextField.FormatValueAsHtml(self, server, 1672 value, 1673 style, name) 1674 1675 # For an editable field, give the user a choice of available 1676 # resources. 1677 items = self.GetItems() 1678 if name is None: 1679 name = self.GetHtmlFormFieldName() 1680 result = '<select name="%s">\n' % name 1681 # HTML does not permit a "select" tag with no contained "option" 1682 # tags. Therefore, we ensure that there is always one option to 1683 # choose from. 1684 result += ' <option value="">--Select--</option>\n' 1685 # Add the choices for the ordinary options. 1686 for r in self.GetItems(): 1687 result += ' <option value="%s"' % r 1688 if r == value: 1689 result += ' selected="selected"' 1690 result += '>%s</option>\n' % r 1691 result += "</select>\n" 1692 1693 return result
1694 1695
1696 - def Validate(self, value):
1697 1698 value = super(ChoiceField, self).Validate(value) 1699 if value == "": 1700 raise ValueError, "No choice specified for %s." % self.GetTitle() 1701 return value
1702 1703 1704
1705 -class EnumerationField(ChoiceField):
1706 """A field that contains an enumeral value. 1707 1708 The enumeral value is selected from an enumerated set of values. 1709 An enumeral field uses the following properties: 1710 1711 enumeration -- A mapping from enumeral names to enumeral values. 1712 Names are converted to strings, and values are stored as integers. 1713 1714 ordered -- If non-zero, the enumerals are presented to the user 1715 ordered by value.""" 1716
1717 - def __init__(self, 1718 name = "", 1719 default_value=None, 1720 enumerals=[], 1721 **properties):
1722 """Create an enumeration field. 1723 1724 'enumerals' -- A sequence of strings of available 1725 enumerals. 1726 1727 'default_value' -- The default value for this enumeration. If 1728 'None', the first enumeral is used.""" 1729 1730 # If we're handed an encoded list of enumerals, decode it. 1731 if isinstance(enumerals, types.StringType): 1732 enumerals = string.split(enumerals, ",") 1733 # Make sure the default value is legitimate. 1734 if not default_value in enumerals and len(enumerals) > 0: 1735 default_value = enumerals[0] 1736 # Perform base class initialization. 1737 super(EnumerationField, self).__init__(name, default_value, 1738 **properties) 1739 # Remember the enumerals. 1740 self.__enumerals = enumerals
1741 1742
1743 - def GetItems(self):
1744 """Return a sequence of enumerals. 1745 1746 returns -- A sequence consisting of string enumerals objects, in 1747 the appropriate order.""" 1748 1749 return self.__enumerals
1750 1751
1752 - def GetHelp(self):
1753 enumerals = self.GetItems() 1754 help = """ 1755 An enumeration field. The value of this field must be one of a 1756 preselected set of enumerals. The enumerals for this field are, 1757 1758 """ 1759 for enumeral in enumerals: 1760 help = help + ' * "%s"\n\n' % enumeral 1761 help = help + ''' 1762 1763 The default value of this field is "%s". 1764 ''' % str(self.GetDefaultValue()) 1765 return help
1766 1767 ### Output methods. 1768
1769 - def MakeDomNodeForValue(self, value, document):
1770 1771 # Store the name of the enumeral. 1772 return xmlutil.create_dom_text_element(document, "enumeral", 1773 str(value))
1774 1775 1776 ### Input methods. 1777
1778 - def GetValueFromDomNode(self, node, attachment_store):
1779 1780 # Make sure 'node' is an '<enumeral>' element. 1781 if node.nodeType != xml.dom.Node.ELEMENT_NODE \ 1782 or node.tagName != "enumeral": 1783 raise qm.QMException, \ 1784 qm.error("dom wrong tag for field", 1785 name=self.GetName(), 1786 right_tag="enumeral", 1787 wrong_tag=node.tagName) 1788 # Extract the value. 1789 return self.Validate(xmlutil.get_dom_text(node))
1790 1791 1792
1793 -class BooleanField(EnumerationField):
1794 """A field containing a boolean value. 1795 1796 The enumeration contains two values: true and false.""" 1797
1798 - def __init__(self, name = "", default_value = None, **properties):
1799 1800 # Construct the base class. 1801 EnumerationField.__init__(self, name, default_value, 1802 ["true", "false"], **properties)
1803 1804
1805 - def Validate(self, value):
1806 1807 if qm.common.parse_boolean(value): 1808 value = "true" 1809 else: 1810 value = "false" 1811 return super(BooleanField, self).Validate(value)
1812 1813 1814 ######################################################################## 1815
1816 -class TimeField(IntegerField):
1817 """A field containing a date and time. 1818 1819 The data and time is stored as seconds since the start of the UNIX 1820 epoch, UTC (the semantics of the standard 'time' function), with 1821 one-second precision. User representations of 'TimeField' fields 1822 show one-minue precision.""" 1823
1824 - def __init__(self, name = "", **properties):
1825 """Create a time field. 1826 1827 The field is given a default value for this field is 'None', which 1828 corresponds to the current time when the field value is first 1829 created.""" 1830 1831 # Perform base class initalization. 1832 super(TimeField, self).__init__(name, None, **properties)
1833 1834
1835 - def GetHelp(self):
1836 if time.daylight: 1837 time_zones = "%s or %s" % time.tzname 1838 else: 1839 time_zones = time.tzname[0] 1840 help = """ 1841 This field contains a time and date. The format for the 1842 time and date is 'YYYY-MM-DD HH:MM ZZZ'. The 'ZZZ' field is 1843 the time zone, and may be the local time zone (%s) or 1844 "UTC". 1845 1846 If the date component is omitted, today's date is used. If 1847 the time component is omitted, midnight is used. If the 1848 time zone component is omitted, the local time zone is 1849 used. 1850 """ % time_zones 1851 default_value = self.GetDefaultValue() 1852 if default_value is None: 1853 help = help + """ 1854 The default value for this field is the current time. 1855 """ 1856 else: 1857 help = help + """ 1858 The default value for this field is %s. 1859 """ % self.FormatValueAsText(default_value) 1860 return help
1861 1862 ### Output methods. 1863
1864 - def FormatValueAsText(self, value, columns=72):
1865 if value is None: 1866 return "now" 1867 else: 1868 return qm.common.format_time(value, local_time_zone=1)
1869 1870
1871 - def FormatValueAsHtml(self, server, value, style, name=None):
1872 1873 value = self.FormatValueAsText(value) 1874 1875 if style == "new" or style == "edit": 1876 return '<input type="text" size="8" name="%s" value="%s" />' \ 1877 % (name, value) 1878 elif style == "full" or style == "brief": 1879 # The time is formatted in three parts: the date, the time, 1880 # and the time zone. Replace the space between the time and 1881 # the time zone with a non-breaking space, so that if the 1882 # time is broken onto two lines, it is broken between the 1883 # date and the time. 1884 date, time, time_zone = string.split(value, " ") 1885 return date + " " + time + "&nbsp;" + time_zone 1886 elif style == "hidden": 1887 return '<input type="hidden" name="%s" value="%s" />' \ 1888 % (name, value) 1889 else: 1890 raise ValueError, style
1891 1892 ### Input methods. 1893
1894 - def ParseTextValue(self, value):
1895 1896 return self.Validate(qm.common.parse_time(value, 1897 default_local_time_zone=1))
1898 1899
1900 - def GetDefaultValue(self):
1901 1902 default_value = super(TimeField, self).GetDefaultValue() 1903 if default_value is not None: 1904 return default_value 1905 1906 return int(time.time())
1907 1908 1909
1910 -class PythonField(Field):
1911 """A 'PythonField' stores a Python value. 1912 1913 All 'PythonField's are computed; they are never written out, nor can 1914 they be specified directly by users. They are used in situations 1915 where the value of the field is specified programatically by the 1916 system.""" 1917
1918 - def __init__(self, name = "", default_value = None):
1919 1920 Field.__init__(self, name, default_value, computed = "true")
1921 1922 ######################################################################## 1923 # Local Variables: 1924 # mode: python 1925 # indent-tabs-mode: nil 1926 # fill-column: 72 1927 # End: 1928

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.file.SubstitutionField-class.html0000664000076400007640000003212211122067147031412 0ustar stefanstefan qm.test.classes.file.SubstitutionField
Package qm :: Package test :: Package classes :: Module file :: Class SubstitutionField
[hide private]
[frames] | no frames]

Class SubstitutionField

source code

   object --+        
            |        
 fields.Field --+    
                |    
fields.TupleField --+
                    |
                   SubstitutionField

A rule for performing a text substitution.

A 'SubstitutionField' consists of a regular expression pattern and a corresponding replacement string. When the substitution is applied to a body of text, all substrings that match the pattern are replaced with the substitution string.

The syntax for the regular expression and the substitution string is that of the standard Python 're' (regular expression) module.

Instance Methods [hide private]
 
__init__(self, name, **properties)
Create a new 'SubstitutionField'.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code

Inherited from fields.TupleField: FormatValueAsHtml, GetSubfields, GetValueFromDomNode, MakeDomNodeForValue, ParseFormValue, Validate

Inherited from fields.Field: FormatValueAsText, GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetTitle, IsComputed, IsHidden, IsReadOnly, ParseTextValue, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from fields.Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name, **properties)
(Constructor)

source code 

Create a new 'SubstitutionField'.

By default, the pattern and replacement string are empty.

Overrides: object.__init__

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: fields.Field.GetHelp
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Var.Call-class.html0000664000076400007640000001504611122067146031472 0ustar stefanstefan qm.external.DocumentTemplate.DT_Var.Call
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Var :: Class Call
[hide private]
[frames] | no frames]

Class Call

source code

Instance Methods [hide private]
 
__init__(self, args) source code
Class Variables [hide private]
  name = 'call'
  expr = None
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler-pysrc.html0000664000076400007640000044153111122067160026664 0ustar stefanstefan qm.test.classes.compiler
Package qm :: Package test :: Package classes :: Module compiler
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.compiler

  1  ######################################################################## 
  2  # 
  3  # File:   compiler.py 
  4  # Author: Mark Mitchell 
  5  # Date:   12/11/2001 
  6  # 
  7  # Contents: 
  8  #   Compiler 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  """Uniform interface to compilers. 
 17   
 18  This module contains the 'Compiler' class which is an abstract base 
 19  class providing a uniform interface to various compilers, such as the 
 20  GNU Compiler Collection and the Edison Design Group compilers.""" 
 21   
 22  ######################################################################## 
 23  # Imports 
 24  ######################################################################## 
 25   
 26  from   qm.executable import * 
 27  import os 
 28  import os.path 
 29  import qm 
 30  import StringIO 
 31  import re 
 32  import sys 
 33  if sys.platform != "win32": 
 34      import resource 
 35   
 36  ######################################################################## 
 37  # Classes 
 38  ######################################################################## 
 39   
40 -class CompilerExecutable(RedirectedExecutable):
41 """A 'CompilerExecutable' is a 'Compiler' that is being run.""" 42
43 - def _InitializeChild(self):
44 """Initialize the child process. 45 46 After 'fork' is called this method is invoked to give the 47 child a chance to initialize itself. '_InitializeParent' will 48 already have been called in the parent process.""" 49 50 # Disable compiler core dumps. 51 if sys.platform != "win32": 52 resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) 53 # Do whatever the base class version would otherwise do. 54 RedirectedExecutable._InitializeChild(self)
55 56
57 - def _StdinPipe(self):
58 """Return a pipe to which to redirect the standard input. 59 60 returns -- A pipe, or 'None' if the standard input should be 61 closed in the child.""" 62 63 # The compiler should not need the standard input. 64 return None
65 66
67 - def _StderrPipe(self):
68 """Return a pipe to which to redirect the standard input. 69 70 returns -- A pipe, or 'None'. If 'None' is returned, but 71 '_StdoutPipe' returns a pipe, then the standard error and 72 standard output will both be redirected to that pipe. However, 73 if '_StdoutPipe' also returns 'None', then the standard error 74 will be closed in the child.""" 75 76 # The standard output and standard error are combined. 77 return None
78 79 80
81 -class Compiler:
82 """A 'Compiler' compiles and links source files.""" 83 84 MODE_PREPROCESS = 'preprocess' 85 """Preprocess the source files, but do not compile them.""" 86 87 MODE_COMPILE = 'compile' 88 """Compile the source files, but do not assemble them.""" 89 90 MODE_ASSEMBLE = 'assemble' 91 """Compile the source files, but do not link them.""" 92 93 MODE_LINK = 'link' 94 """Compile and link the source files.""" 95 96 modes = [ MODE_COMPILE, MODE_ASSEMBLE, MODE_LINK, MODE_PREPROCESS ] 97 """The available compilation modes.""" 98
99 - def __init__(self, path, options=None, ldflags=None):
100 """Construct a new 'Compiler'. 101 102 'path' -- A string giving the location of the compiler 103 executable. 104 105 'options' -- A list of strings indicating options to the 106 compiler, or 'None' if there are no options. 107 108 'ldflags' -- A list of strings indicating ld flags to the 109 compiler, or 'None' if there are no flags.""" 110 111 self._path = path 112 self.SetOptions(options or []) 113 self.SetLDFlags(ldflags or [])
114 115
116 - def Compile(self, mode, files, dir, options = [], ldflags = [], 117 output = None, timeout = -1):
118 """Compile the 'files'. 119 120 'mode' -- The compilation mode (one of the 'Compiler.modes') 121 that should be used to compile the 'files'. 122 123 'files' -- A sequence of strings giving the names of source 124 files (including, in general, assembly files, object files, 125 and libraries) that should be compiled. 126 127 'dir' -- The directory in which to run the compiler. 128 129 'options' -- A sequence of strings indicating additional 130 options that should be provided to the compiler. 131 132 'ldflags' -- A sequence of strings indicating additional 133 linker flags that should be provided to the compiler, if 134 linking is done. 135 136 'output' -- The name of the file should be created by the 137 compilation. If 'None', the compiler will use a default 138 value. 139 140 'timeout' -- The maximum number of seconds the compiler is 141 permitted to run. If 'timeout' is -1, the compiler is 142 permitted to run forever. 143 144 returns -- A tuple '(status, output)'. The 'status' is the 145 exit status returned by the compiler, as indicated by 146 'waitpid'. The 'output' is a string containing the standard 147 outpt and standard errror generated by the compiler.""" 148 149 # Get the command to use. 150 command = self.GetCompilationCommand(mode, files, options, 151 ldflags, output) 152 # Invoke the compiler. 153 return self.ExecuteCommand(dir, command, timeout)
154 155
156 - def ExecuteCommand(self, dir, command, timeout = -1):
157 """Execute 'command' in 'dir'. 158 159 'dir' -- The directory in which to execute the command. 160 161 'command' -- A sequence of strings, as returned by 162 'GetCompilationCommand'. 163 164 'timeout' -- The maximum number of seconds the compiler is 165 permitted to run. If 'timeout' is -1, the compiler is 166 permitted to run forever. 167 168 returns -- A tuple '(status, output)'. The 'status' is the 169 exit status returned by the compiler, as indicated by 170 'waitpid'. The 'output' is a string containing the standard 171 output and standard errror generated by the compiler.""" 172 173 # Invoke the compiler. 174 executable = CompilerExecutable(timeout) 175 status = executable.Run(command, dir = dir) 176 # Return all of the information. 177 return (status, executable.stdout)
178 179
180 - def GetCompilationCommand(self, mode, files, options=[], 181 ldflags = [], output=None):
182 """Return the appropriate command for compiling 'files'. 183 184 'mode' -- The compilation mode (one of the 'Compiler.modes') 185 that should be used to compile the 'files'. 186 187 'files' -- A sequence of strings giving the names of source 188 files (including, in general, assembly files, object files, 189 and libraries) that should be compiled. 190 191 'options' -- A sequence of strings indicating additional 192 options that should be provided to the compiler. 193 194 'ldflags' -- A sequence of strings indicating additional 195 linker flags that should be provided to the compiler, if 196 linking is done. 197 198 'output' -- The name of the file should be created by the 199 compilation. If 'None', the compiler will use a default 200 value. (In some cases there may be multiple outputs. For 201 example, when generating multiple object files from multiple 202 source files, the compiler will create a variety of objects.) 203 204 returns -- A sequence of strings indicating the arguments, 205 including 'argv[0]', for the compilation command.""" 206 207 # Start with the path to the compiler. 208 command = [self.GetPath()] 209 # Add switches indicating the compilation mode, if appropriate. 210 command += self._GetModeSwitches(mode) 211 # Add the options that should be used with every compilation. 212 command += self._options 213 # Add the options that apply to this compilation. 214 command += options 215 # Set the output file. 216 if output: 217 command += ["-o", output] 218 # Add the input files. 219 command += files 220 if mode == Compiler.MODE_LINK: 221 command += ldflags 222 command += self.GetLDFlags() 223 224 return command
225 226
227 - def ParseOutput(self, output, ignore_regexps = ()):
228 """Turn the 'output' into a sqeuence of 'Diagnostic's. 229 230 'output' -- A string containing the compiler's output. 231 232 'ignore_regexps' -- A sequence of regular expressions. If a 233 diagnostic message matches one of these regular expressions, 234 it will be ignored. 235 236 returns -- A list of 'Diagnostic's corresponding to the 237 messages indicated in 'output', in the order that they were 238 emitted.""" 239 240 raise NotImplementedError
241 242
243 - def GetPath(self):
244 """Return the location of the executable. 245 246 returns -- A string giving the location of the executable. 247 This location is the one that was specified as the 'path' 248 argument to '__init__'.""" 249 250 return self._path
251 252
253 - def GetOptions(self):
254 """Return the list of compilation options. 255 256 returns -- A list of strings giving the compilation options 257 specified when the 'Compiler' was constructed.""" 258 259 return self._options
260 261
262 - def SetOptions(self, options):
263 """Reset the list of compiler options. 264 265 'options' -- A list of strings indicating options to the 266 compiler, or 'None' if there are no options.""" 267 268 self._options = options
269 270
271 - def GetLDFlags(self):
272 """Return the list of link options. 273 274 returns -- A list of strings giving the link options 275 specified when the 'Compiler' was constructed.""" 276 277 return self._ldflags
278 279
280 - def SetLDFlags(self, ldflags):
281 """Reset the list of link options. 282 283 'ldflags' -- A list of strings indicating options to the 284 linker, or 'None' if there are no flags.""" 285 286 self._ldflags = ldflags
287 288
289 - def GetExecutableExtension(self):
290 """Return the extension for executables. 291 292 returns -- The extension (including leading '.', if 293 applicable) for executable files created by this compiler.""" 294 295 if sys.platform == "win32": 296 return ".exe" 297 else: 298 return ""
299 300
301 - def GetObjectExtension(self):
302 """Return the extension for object files. 303 304 returns -- The extension (including leading '.', if 305 applicable) for object files created by this compiler.""" 306 307 if sys.platform == "win32": 308 return ".obj" 309 else: 310 return ".o"
311 312
313 - def _GetModeSwitches(self, mode):
314 """Return the compilation switches for the compilation 'mode'. 315 316 'mode' -- The compilation mode (one of 'Compiler.modes'). 317 318 returns -- A sequence of strings indicating the switches that 319 are used to indicate the compilation mode.""" 320 321 if mode == self.MODE_PREPROCESS: 322 return ["-E"] 323 elif mode == self.MODE_COMPILE: 324 return ["-S"] 325 elif mode == self.MODE_ASSEMBLE: 326 return ["-c"] 327 328 # Other modes require no special option. 329 return []
330 331 332
333 -class SourcePosition:
334 """A 'SourcePosition' indicates a location in source code. 335 336 A 'SourcePosition' consists of: 337 338 - A file name. The file name is a string. It may be an absolute 339 or relative path. If no file name is available, the file name 340 is the empty string. 341 342 - A line number, indexed from one. If no line number is 343 available, the line number is zero. 344 345 - A column number, indexed from one. If no column number is 346 available, the column nubmer is zero.""" 347
348 - def __init__(self, file, line, column):
349 """Construct a new 'SourcePosition'. 350 351 'file' -- The file name. 352 353 'line' -- The line number, indexed from one. If no line numer 354 is availble, use zero for this parameter. 355 356 'column' -- The column number, indexed from one. If no column 357 number is available, use zero for this parameter.""" 358 359 self.file = file 360 self.line = line 361 self.column = column
362 363
364 - def __str__(self):
365 """Return a textual representation of this 'SourcePosition'. 366 367 returns -- A string representing this 'SourcePosition'""" 368 369 result = '' 370 if self.file: 371 result = result + '"%s"' % os.path.split(self.file)[0] 372 if self.line: 373 if self.file: 374 result = result + ', ' 375 result = result + 'line %d' % self.line 376 if self.column: 377 result = result + ': %d' % self.column 378 379 return result
380 381 382
383 -class Diagnostic:
384 """A 'Diagnostic' is a message issued by a compiler. 385 386 Each 'Diagnostic' has the following attributes: 387 388 - The source position that the compiler associates with the 389 diagnostic. 390 391 - The severity of the diagnostic. 392 393 - The message issued by the compiler. 394 395 A 'Diagnostic' may either be an actual diagnostic emitted by a 396 compiler, or it may be the pattern for a diagnostic that might be 397 emitted. In the latter case, the message is a regular expression 398 indicating the message that should be emitted.""" 399
400 - def __init__(self, source_position, severity, message):
401 """Construct a new 'Diagnostic'. 402 403 'source_position' -- A 'SourcePosition' indicating where the 404 diagnostic was issued. For an expected diagnostic, 'None' 405 indicates that the position does not matter. 406 407 'severity' -- A string indicating the severity of the 408 diagnostic. For an expected diagnostic, 'None' indicates 409 that the severity does not matter. 410 411 'message' -- For an emitted diagnostic, a string indicating 412 the message produced by the compiler. For an expected 413 diagnostic, a string giving a regular expression indicating 414 the message that might be emitted. For an expected 415 diagnostic, 'None' indicates that the message does not 416 matter.""" 417 418 self.source_position = source_position 419 self.severity = severity 420 self.message = message
421 422
423 - def __str__(self):
424 """Return an informal representation of this 'Diagnostic'. 425 426 returns -- A string representing this 'Diagnostic'.""" 427 428 if self.source_position: 429 source_position_string = str(self.source_position) 430 else: 431 source_position_string = "<no source position>" 432 433 if self.severity: 434 severity_string = self.severity 435 else: 436 severity_string = "<no severity>" 437 438 if self.message: 439 message_string = self.message 440 else: 441 message_string = "<no message>" 442 443 return '%s: %s: %s' % (source_position_string, 444 severity_string, 445 message_string)
446 447 448 ######################################################################## 449 # Compilers 450 ######################################################################## 451
452 -class GCC(Compiler):
453 """A 'GCC' is a GNU Compiler Collection compiler.""" 454 455 _severities = [ 'warning', 'error' ] 456 """The diagnostic severities generated by the compiler. Order 457 matters; the order given here is the order that the 458 '_severity_regexps' will be tried.""" 459 460 _severity_regexps = { 461 'warning' : 462 re.compile('^(?P<file>[^:]*):((?P<line>[^:]*):)?' 463 '(\s*(?P<column>[0-9]+):)? ' 464 'warning: (?P<message>.*)$'), 465 'error': 466 re.compile('^(?P<file>[^:]*):((?P<line>[^:]*):)?' 467 '(\s*(?P<column>[0-9]+):)? ' 468 '(?P<message>.*)$') 469 } 470 """A map from severities to compiled regular expressions. If the 471 regular expression matches a line in the compiler output, then that 472 line indicates a diagnostic with the indicated severity.""" 473 474 _internal_error_regexp = re.compile('Internal (compiler )?error') 475 """A compiled regular expression. When an error message is matched 476 by this regular expression, the error message indicates an 477 internal error in the compiler.""" 478 479 MODE_PRECOMPILE = "precompile" 480 """Precompile a header file.""" 481 482 modes = Compiler.modes + [MODE_PRECOMPILE] 483
484 - def ParseOutput(self, output, ignore_regexps = ()):
485 """Return the 'Diagnostic's indicated in the 'output'. 486 487 'output' -- A string giving the output from the compiler. 488 489 'ignore_regexps' -- A sequence of regular expressions. If a 490 diagnostic message matches one of these regular expressions, 491 it will be ignored. 492 493 returns -- A list of 'Diagnostic's corresponding to the 494 messages indicated in 'output', in the order that they were 495 emitted.""" 496 497 # Assume there were no diagnostics. 498 diagnostics = [] 499 # Create a file object containing the 'output'. 500 f = StringIO.StringIO(output) 501 # Reall all of the output, line by line. 502 for line in f.readlines(): 503 for severity in self._severities: 504 match = self._severity_regexps[severity].match(line) 505 # If it does not look like an error message, skip it. 506 if not match: 507 continue 508 509 # Some error messages are ignored. 510 ignore = 0 511 for ignore_regexp in ignore_regexps: 512 if ignore_regexp.match(match.group()): 513 ignore = 1 514 break 515 if ignore: 516 continue 517 518 # An internal error is an error that indicates that 519 # the compiler crashed. 520 message = match.group('message') 521 if (severity == 'error' 522 and self._internal_error_regexp.search(message)): 523 severity = 'internal_error' 524 525 # If there is no line number, then we will not be 526 # able to convert it to an integer. 527 try: 528 line_number = int(match.group('line')) 529 except: 530 line_number = 0 531 532 # See if there is a column number. 533 try: 534 column_number = int(match.group('column')) 535 except: 536 column_number = 0 537 538 source_position = SourcePosition(match.group('file'), 539 line_number, 540 column_number) 541 diagnostic = Diagnostic(source_position, 542 severity, 543 message) 544 diagnostics.append(diagnostic) 545 break 546 547 return diagnostics
548 549 550
551 -class EDG(Compiler):
552 """An 'EDG' is an Edison Design Group compiler.""" 553 554 __diagnostic_regexp = re.compile('^"(?P<file>.*)", line (?P<line>.*): ' 555 '(?P<severity>.*): (?P<message>.*)$') 556
557 - def ParseOutput(self, output, ignore_regexps = ()):
558 """Return the 'Diagnostic's indicated in the 'output'. 559 560 'output' -- A string giving the output from the compiler. 561 562 'ignore_regexps' -- A sequence of regular expressions. If a 563 diagnostic message matches one of these regular expressions, 564 it will be ignored. 565 566 returns -- A list of 'Diagnostic's corresponding to the 567 messages indicated in 'output', in the order that they were 568 emitted.""" 569 570 # Assume there were no diagnostics. 571 diagnostics = [] 572 # Create a file object containing the 'output'. 573 f = StringIO.StringIO(output) 574 # Reall all of the output, line by line. 575 for line in f.readlines(): 576 match = self.__diagnostic_regexp.match(line) 577 if match: 578 source_position = SourcePosition(match.group('file'), 579 int(match.group('line')), 580 0) 581 diagnostic = Diagnostic(source_position, 582 match.group('severity'), 583 match.group('message')) 584 diagnostics.append(diagnostic) 585 586 587 return diagnostics
588

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.cmdline-module.html0000664000076400007640000000225011122067144024754 0ustar stefanstefan cmdline

Module cmdline


Classes

CommandError
CommandParser

[hide private] ././@LongLink0000000000000000000000000000016700000000000011571 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test_database.CompilationTestDatabase-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test_database.CompilationTestD0000664000076400007640000007114711122067147033402 0ustar stefanstefan qm.test.classes.compilation_test_database.CompilationTestDatabase
Package qm :: Package test :: Package classes :: Module compilation_test_database :: Class CompilationTestDatabase
[hide private]
[frames] | no frames]

Class CompilationTestDatabase

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
      database.Database --+
                          |
                         CompilationTestDatabase

A 'CompilationTestDatabase' test database maps source code files to compilation tests.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, path, arguments)
Construct a 'Database'.
source code
 
GetSubdirectories(self, directory)
Return the immediate subdirectories of 'directory'.
source code
 
GetIds(self, kind, directory='', scan_subdirs=1)
Return all IDs of the indicated 'kind' that begin with 'directory'.
source code
 
GetExtension(self, id)
Return the extension object named 'id'.
source code
 
_MakeTest(self, test_id, language) source code

Inherited from database.Database: ExpandIds, GetAttachmentStore, GetClassPaths, GetConfigurationDirectory, GetExtensions, GetItem, GetLabelComponents, GetPath, GetResource, GetResourceClassNames, GetResourceIds, GetSuite, GetSuiteIds, GetTest, GetTestClassNames, GetTestIds, HasResource, HasSuite, HasTest, IsModifiable, IsValidLabel, JoinLabels, RemoveExtension, SplitLabel, SplitLabelLeft, WriteExtension

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  srcdir = TextField(title= "Source Directory", description= "Th...
  excluded_subdirs = SetField(TextField(), default_value= ['QMTe...
  test_extensions = DictionaryField(TextField(), EnumerationFiel...
  _is_generic_database = True
True if this database implements 'GetExtension' as a primitive.

Inherited from database.Database: ITEM_KINDS, RESOURCE, SUITE, TEST, arguments, kind, label_class, modifiable

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, path, arguments)
(Constructor)

source code 

Construct a 'Database'.

'path' -- A string containing the absolute path to the directory containing the database.

'arguments' -- A dictionary mapping attribute names to values. The use of this parameter is deprecated. Use keyword arguments instead.

Derived classes must call this method from their own '__init__' methods. Every derived class must have an '__init__' method that takes the path to the directory containing the database as its only argument. The path provided to the derived class '__init__' function will always be an absolute path.

Overrides: object.__init__
(inherited documentation)

GetSubdirectories(self, directory)

source code 

Return the immediate subdirectories of 'directory'.

'directory' -- A label indicating a directory in the database.

returns -- A sequence of (relative) labels indictating the immediate subdirectories of 'directory'. For example, if "a.b" and "a.c" are directories in the database, this method will return "b" and "c" given "a" as 'directory'.

Derived classes may override this method.

Overrides: database.Database.GetSubdirectories
(inherited documentation)

GetIds(self, kind, directory='', scan_subdirs=1)

source code 

Return all IDs of the indicated 'kind' that begin with 'directory'.

'kind' -- One of the 'ITEM_KINDS'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

returns -- A list of all items of the indicated 'kind' located within 'directory', as absolute labels.

Derived classes may override this method.

Overrides: database.Database.GetIds
(inherited documentation)

GetExtension(self, id)

source code 

Return the extension object named 'id'.

'id' -- The label for the extension.

returns -- The instance of 'Extension' with the indicated name, or 'None' if there is no such entity.

Database classes should override this method. For backwards compatibility, this base class implements this generic method in terms of the special-purpose methods 'GetTest()' and 'GetResource()'. Only if _is_generic_database is True are these implemented in terms of 'GetExtension()'.

Overrides: database.Database.GetExtension
(inherited documentation)

Class Variable Details [hide private]

srcdir

Value:
TextField(title= "Source Directory", description= "The root of the tes\
t suite's source tree.")

excluded_subdirs

Value:
SetField(TextField(), default_value= ['QMTest', 'CVS', '.svn', 'build'\
])

test_extensions

Value:
DictionaryField(TextField(), EnumerationField(enumerals= ['c', 'cplusp\
lus']), default_value= {'.c': 'c', '.cpp': 'cplusplus', '.cxx': 'cplus\
plus', '.cc': 'cplusplus', '.C': 'cplusplus', '.f': 'fortran'})

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.gparse-pysrc.html0000664000076400007640000030614011122067154031012 0ustar stefanstefan qm.external.DocumentTemplate.gparse
Package qm :: Package external :: Package DocumentTemplate :: Module gparse
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.gparse

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  "$Id: gparse.py 1069 2008-11-13 21:55:43Z stefan $" 
 14  import sys, parser, symbol, token 
 15   
 16  from symbol import test, suite, argument, arith_expr, shift_expr 
 17  from symbol import subscriptlist, subscript, comparison, trailer, xor_expr 
 18  from symbol import term, not_test, factor, atom, expr, arglist 
 19  from symbol import power, and_test, and_expr 
 20   
 21  from token import STAR, NAME, RPAR, LPAR, NUMBER, DOT, STRING, COMMA 
 22  from token import ISTERMINAL, LSQB, COLON 
 23   
 24  from parser import sequence2ast, compileast, ast2list 
 25   
 26  ParseError='Expression Parse Error' 
 27   
28 -def munge(ast, STAR=STAR, DOT=DOT, LSQB=LSQB, COLON=COLON, trailer=trailer):
29 ast0=ast[0] 30 if ISTERMINAL(ast0): return 31 else: 32 if ast0==term and len(ast) > 2: 33 keep_going=1 34 while keep_going: 35 keep_going=0 36 start=2 37 for i in range(start,len(ast)-1): 38 if ast[i][0]==STAR: 39 ast[i-1:i+2]=[multi_munge(ast[i-1:i+2])] 40 keep_going=1 41 break 42 43 for a in ast[1:]: munge(a) 44 45 elif ast0==power: 46 keep_going=1 47 while keep_going: 48 keep_going=0 49 start=2 50 for i in range(start,len(ast)): 51 a=ast[i] 52 if a[0]==trailer: 53 if a[1][0]==DOT: 54 ast[:i+1]=dot_munge(ast,i) 55 keep_going=1 56 start=3 57 break 58 if a[1][0]==LSQB: 59 if (a[2][0] != subscriptlist or 60 a[2][1][0] != subscript): 61 raise ParseError, ( 62 'Unexpected form after left square brace') 63 64 slist=a[2] 65 if len(slist)==2: 66 # One subscript, check for range and ... 67 sub=slist[1] 68 if sub[1][0]==DOT: 69 raise ParseError, ( 70 'ellipses are not supported') 71 l=len(sub) 72 if l < 3 and sub[1][0] != COLON: 73 ast[:i+1]=item_munge(ast, i) 74 elif l < 5: ast[:i+1]=slice_munge(ast, i) 75 else: raise ParseError, 'Invalid slice' 76 77 else: ast[:i+1]=item_munge(ast, i) 78 keep_going=1 79 start=3 80 break 81 82 for a in ast[1:]: munge(a) 83 else: 84 for a in ast[1:]: munge(a) 85 return ast
86
87 -def slice_munge(ast, i):
88 # Munge a slice access into a function call 89 # Note that we must account for a[:], a[b:], a[:b], and a[b:c] 90 name=ast[i][2][1] 91 args=[arglist] 92 append=args.append 93 94 a=(factor, (power, (atom, (NAME, '_vars')))) 95 a=(argument, (test, (and_test, (not_test, (comparison, 96 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 97 (term, a))))))))))) 98 append(a) 99 append([COMMA,',']) 100 101 a=ast[:i] 102 a=(argument, (test, (and_test, (not_test, (comparison, 103 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 104 (term, (factor, a)))))))))))) 105 append(a) 106 107 sub=ast[i][2][1] 108 l=len(sub) 109 if sub[1][0]==COLON: 110 if l==3: 111 append([COMMA,',']) 112 a=(argument, (test, (and_test, (not_test, (comparison, 113 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 114 (term, (factor, (power, (atom, (NUMBER, '0'))))))))))))))) 115 append(a) 116 append([COMMA,',']) 117 append([argument, sub[2]]) 118 else: 119 append([COMMA,',']) 120 append([argument, sub[1]]) 121 if l==4: 122 append([COMMA,',']) 123 append([argument, sub[3]]) 124 125 return [power, [atom, [NAME, '__guarded_getslice__']], 126 [trailer, [LPAR, '('], args, [RPAR, ')'], 127 ] 128 ]
129
130 -def item_munge(ast, i):
131 # Munge an item access into a function call 132 name=ast[i][2][1] 133 args=[arglist] 134 append=args.append 135 136 a=(factor, (power, (atom, (NAME, '_vars')))) 137 a=(argument, (test, (and_test, (not_test, (comparison, 138 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 139 (term, a))))))))))) 140 append(a) 141 append([COMMA,',']) 142 143 a=ast[:i] 144 a=(argument, (test, (and_test, (not_test, (comparison, 145 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 146 (term, (factor, a)))))))))))) 147 append(a) 148 append([COMMA,',']) 149 150 for sub in ast[i][2][1:]: 151 if sub[0]==COMMA: append(sub) 152 else: 153 if len(sub) != 2: raise ParseError, 'Invalid slice in subscript' 154 append([argument, sub[1]]) 155 156 return [power, [atom, [NAME, '__guarded_getitem__']], 157 [trailer, [LPAR, '('], args, [RPAR, ')'], 158 ] 159 ]
160
161 -def dot_munge(ast, i):
162 # Munge an attribute access into a function call 163 name=ast[i][2][1] 164 args=[arglist] 165 append=args.append 166 167 a=(factor, (power, (atom, (NAME, '_vars')))) 168 a=(argument, (test, (and_test, (not_test, (comparison, 169 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 170 (term, a))))))))))) 171 append(a) 172 append([COMMA,',']) 173 174 a=ast[:i] 175 a=(argument, (test, (and_test, (not_test, (comparison, 176 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 177 (term, (factor, a)))))))))))) 178 append(a) 179 append([COMMA,',']) 180 181 a=(factor, (power, (atom, (STRING, `name`)))) 182 a=(argument, (test, (and_test, (not_test, (comparison, 183 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 184 (term, a))))))))))) 185 append(a) 186 187 return [power, [atom, [NAME, '__guarded_getattr__']], 188 [trailer, [LPAR, '('], args, [RPAR, ')']], 189 ]
190
191 -def multi_munge(ast):
192 # Munge a multiplication into a function call: __guarded_mul__ 193 args=[arglist] 194 195 append=args.append 196 a=(factor, (power, (atom, (NAME, '_vars')))) 197 a=(argument, (test, (and_test, (not_test, (comparison, 198 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 199 (term, a))))))))))) 200 append(a) 201 append([COMMA,',']) 202 203 for a in ast: 204 if a[0]==STAR: args.append([COMMA,',']) 205 else: 206 a=(argument, (test, (and_test, (not_test, (comparison, 207 (expr, (xor_expr, (and_expr, (shift_expr, (arith_expr, 208 (term, a))))))))))) 209 append(a) 210 211 return [factor, [power, 212 [atom, [NAME, '__guarded_mul__']], 213 [trailer, [LPAR, '('], args, [RPAR, ')'], 214 ]]]
215
216 -def compile(src, file_name, ctype):
217 if ctype=='eval': ast=parser.expr(src) 218 elif ctype=='exec': ast=parser.suite(src) 219 l=ast2list(ast) 220 l=munge(l) 221 ast=sequence2ast(l) 222 return parser.compileast(ast, file_name)
223

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.DirPage-class.html0000664000076400007640000011137111122067151026222 0ustar stefanstefan qm.test.web.web.DirPage
Package qm :: Package test :: Package web :: Module web :: Class DirPage
[hide private]
[frames] | no frames]

Class DirPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      DirPage

A test database directory page.

These attributes are available in DTML:

'path' -- The label directory that is being displayed.

'subdirs' -- A sequence of labels giving the subdirectories of this directory.

'test_ids' -- A sequence of labels giving the tests in this directory.

'suite_ids' -- A sequence of labels giving the suites in this directory.

'resource_ids' -- A sequence of labels giving the resources in this directory.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, path)
Construct a 'DirPage'.
source code
 
GetRunUrl(self)
Return the URL for running this directory.
source code
 
GetTestResultsForDirectory(self, directory)
Return all of the test results for tests in 'directory'.
source code
 
GetUnexpectedResultsByOutcome(self, results)
Compute the tests in 'results' with each outcome.
source code
 
GetUnexpectedOutcomePercentages(self, results)
Compute percentages of unexpected 'results'.
source code
 
CountUnexpected(self, results)
Count the unexpected 'results'.
source code
 
GetResultURL(self, id, kind)
Generate a URL for the result page for 'id'.
source code
 
GetTests(self, sort)
Return information about all of the tests.
source code
 
GetTestOutcome(self, test_id)
Return the 'Result' for 'test_id'.
source code
 
GetDetailURL(self, test_id)
Return the detail URL for 'test_id'.
source code
 
GetExpectation(self, test_id)
Return the expected outcome for 'test_id'.
source code
 
GetSortURL(self, sort)
Get the URL for this page, but sorted as indicated.
source code
 
IsFinished(self)
Return true iff no more results are forthcoming.
source code
 
GetRefreshDelay(self)
Returns the number of seconds to wait before refreshing the page.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]
  SORT_NAME = 'name'
Sort by name.
  SORT_OUTCOME = 'outcome'
Sort by outcome.
  SORT_EXPECTATION = 'expectation'
Sort by expectation.
  SORT_KINDS = [SORT_NAME, SORT_OUTCOME, SORT_EXPECTATION]
The kinds of sorting available.

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, path)
(Constructor)

source code 

Construct a 'DirPage'.

'server' -- The 'QMTestServer' creating this page.

'path' -- The label directory to display.

Overrides: web.DtmlPage.__init__

GetTestResultsForDirectory(self, directory)

source code 

Return all of the test results for tests in 'directory'.

'directory' -- A string giving the label for a directory.

returns -- A sequence of 'Result' instances corresponding to results for tests from the indicated directory.

GetUnexpectedResultsByOutcome(self, results)

source code 

Compute the tests in 'results' with each outcome.

'results' -- A sequence of 'Result' instances.

returns -- A dictionary mapping outcomes to the results with that outcome -- and for which that outcome is unexpected. The (fake) outcome 'self.EXPECTED' is mapped to expected results.

GetUnexpectedOutcomePercentages(self, results)

source code 

Compute percentages of unexpected 'results'.

'results' -- A sequence of 'Result' instances.

returns -- A dictionary mapping the 'EXPECTATION_KINDS' to the percentage (as a floating point number) of tests in 'results' that have that expectation.

CountUnexpected(self, results)

source code 

Count the unexpected 'results'.

'results' -- A dictionary of the form returned by 'GetUnexpectedResultsByOutcome'.

returns -- The total number of unexpected results.

GetResultURL(self, id, kind)

source code 

Generate a URL for the result page for 'id'.

'id' -- The name of a test or resource.

'kind' -- either 'test' or 'resource'.

returns -- A url string for the result page for 'id'.

GetTests(self, sort)

source code 

Return information about all of the tests.

'sort' -- One of the 'SORT_KINDS' indicating how the results should be sorted.

returns -- A sequence of 'Item' instances corresponding to all of the tests in this diretory.

GetTestOutcome(self, test_id)

source code 

Return the 'Result' for 'test_id'.

'test_id' -- The name of the test whose result is requested.

'result' -- The result associated with the 'test_id', or 'None' if no result is available.

GetDetailURL(self, test_id)

source code 

Return the detail URL for 'test_id'.

'test_id' -- The name of the test.

returns -- The URL that contains details about the 'test_id'.

GetExpectation(self, test_id)

source code 

Return the expected outcome for 'test_id'.

'test_id' -- The name of the test.

returns -- A string giving the expected outcome for 'test_id', or 'None' if there is no expectation.

GetSortURL(self, sort)

source code 

Get the URL for this page, but sorted as indicated.

'sort' -- One of the 'SORT_KINDS'.

returns -- A URL indicating this page, but sorted as indicated.

IsFinished(self)

source code 

Return true iff no more results are forthcoming.

returns -- True if no more tests are running.

Overrides: QMTestPage.IsFinished

GetRefreshDelay(self)

source code 

Returns the number of seconds to wait before refreshing the page.

returns -- The number of seconds to wait before refreshing this page. A value of zero means that te page should never be refreshed. This function is only called if 'IsFinished' returns true.

Overrides: QMTestPage.GetRefreshDelay

Class Variable Details [hide private]

SORT_EXPECTATION

Sort by expectation. In other words, put unexpected outcomes before expected outcomes.

Value:
'expectation'

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.cmdline-module.html0000664000076400007640000000301711122067144025734 0ustar stefanstefan cmdline

Module cmdline


Classes

QMTest

Functions

get_qmtest

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Util.Eval-class.html0000664000076400007640000001650511122067146031674 0ustar stefanstefan qm.external.DocumentTemplate.DT_Util.Eval
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Util :: Class Eval
[hide private]
[frames] | no frames]

Class Eval

source code

VSEval.Eval --+
              |
             Eval

Instance Methods [hide private]
 
eval(self, mapping) source code

Inherited from VSEval.Eval: __call__, __init__

Method Details [hide private]

eval(self, mapping)

source code 
Overrides: VSEval.Eval.eval

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.db-module.html0000664000076400007640000000226011122067144023727 0ustar stefanstefan db

Module db


Classes

Connection

Functions

quote_string

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler.Diagnostic-class.html0000664000076400007640000002306011122067147030712 0ustar stefanstefan qm.test.classes.compiler.Diagnostic
Package qm :: Package test :: Package classes :: Module compiler :: Class Diagnostic
[hide private]
[frames] | no frames]

Class Diagnostic

source code

A 'Diagnostic' is a message issued by a compiler.

Each 'Diagnostic' has the following attributes:

- The source position that the compiler associates with the
  diagnostic.

- The severity of the diagnostic.

- The message issued by the compiler.

A 'Diagnostic' may either be an actual diagnostic emitted by a
compiler, or it may be the pattern for a diagnostic that might be
emitted.  In the latter case, the message is a regular expression
indicating the message that should be emitted.

Instance Methods [hide private]
 
__init__(self, source_position, severity, message)
Construct a new 'Diagnostic'.
source code
 
__str__(self)
Return an informal representation of this 'Diagnostic'.
source code
Method Details [hide private]

__init__(self, source_position, severity, message)
(Constructor)

source code 

Construct a new 'Diagnostic'.

'source_position' -- A 'SourcePosition' indicating where the diagnostic was issued. For an expected diagnostic, 'None' indicates that the position does not matter.

'severity' -- A string indicating the severity of the diagnostic. For an expected diagnostic, 'None' indicates that the severity does not matter.

'message' -- For an emitted diagnostic, a string indicating the message produced by the compiler. For an expected diagnostic, a string giving a regular expression indicating the message that might be emitted. For an expected diagnostic, 'None' indicates that the message does not matter.

__str__(self)
(Informal representation operator)

source code 

Return an informal representation of this 'Diagnostic'.

returns -- A string representing this 'Diagnostic'.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.TestDescriptor-class.html0000664000076400007640000003647211122067150030107 0ustar stefanstefan qm.test.database.TestDescriptor
qm :: test :: database :: TestDescriptor :: Class TestDescriptor
[hide private]
[frames] | no frames]

Class TestDescriptor

source code

ItemDescriptor --+
                 |
                TestDescriptor

A test instance.

Instance Methods [hide private]
 
__init__(self, database, test_id, test_class_name=None, arguments=None, test=None)
Create a new test instance.
source code
 
GetClass(self)
Return the class of the entity.
source code
 
GetTest(self)
Return the 'Test' object described by this descriptor.
source code
 
GetPrerequisites(self)
Return a map from prerequisite test IDs to required outcomes.
source code
 
GetTargetGroup(self)
Returns the pattern for the targets that can run this test.
source code
 
Run(self, context, result)
Execute this test.
source code

Inherited from ItemDescriptor: GetArguments, GetClassArguments, GetClassName, GetDatabase, GetId, GetItem, GetResources

Inherited from ItemDescriptor (private): _Execute

Method Details [hide private]

__init__(self, database, test_id, test_class_name=None, arguments=None, test=None)
(Constructor)

source code 

Create a new test instance.

'database' -- The 'Database' containing this test.

'test_id' -- The test ID.

'test_class_name' -- The name of the test class of which this is an instance. Omit this argument if 'test' is provided.

'arguments' -- This test's arguments to the test class. Omit this argument if 'test' is provided.

'test' -- The test class of which this is an instance.

Overrides: ItemDescriptor.__init__

GetClass(self)

source code 

Return the class of the entity.

returns -- The Python class object for the entity. For example, for a 'TestDescriptor', this method returns the test class.

Overrides: ItemDescriptor.GetClass

GetTargetGroup(self)

source code 

Returns the pattern for the targets that can run this test.

returns -- A regular expression (represented as a string) that indicates the targets on which this test can be run. If the pattern matches a particular group name, the test can be run on targets in that group.

Run(self, context, result)

source code 

Execute this test.

'context' -- The 'Context' in which the test should be executed.

'result' -- The 'Result' object for this test.


././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.expectation_database.ExpectationDatabase-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.expectation_database.ExpectationDatabase-class.htm0000664000076400007640000004345111122067150033263 0ustar stefanstefan qm.test.expectation_database.ExpectationDatabase
Package qm :: Package test :: Module expectation_database :: Class ExpectationDatabase
[hide private]
[frames] | no frames]

Class ExpectationDatabase

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     ExpectationDatabase

An 'ExpectationDatabase' stores result expectations.

An 'ExpectationDatabase' provides a mechanism to store and make accessible expectations for test outcomes. By default, all tests are expected to pass.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Lookup(self, test_id)
Look up the expected outcome for the given test.
source code
 
GetExpectedOutcomes(self)
Return a dict object mapping test ids to expected outcomes.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__, __init__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  kind = 'expectation_database'
A string giving kind of extension is implemented by the class.
  test_database = None
  testrun_parameters = None
  _argument_dictionary = {'test_database': <<class 'qm.fields.Py...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.PythonField'> test_databa...
A list of all the 'Field's in this class.

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Lookup(self, test_id)

source code 

Look up the expected outcome for the given test.

'test_id' -- test-id for which the outcome is queried.

returns -- a Result object associated with this test_id.


Class Variable Details [hide private]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'test_database': <<class 'qm.fields.PythonField'> test_database>,
 'testrun_parameters': <<class 'qm.fields.PythonField'> testrun_parame\
ters>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.PythonField'> test_database>,
 <<class 'qm.fields.PythonField'> testrun_parameters>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dir_run_database-pysrc.html0000664000076400007640000005025411122067152030337 0ustar stefanstefan qm.test.classes.dir_run_database
Package qm :: Package test :: Package classes :: Module dir_run_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.dir_run_database

 1  ######################################################################## 
 2  # 
 3  # File:   dir_run_database.py 
 4  # Author: Mark Mitchell 
 5  # Date:   2005-08-08 
 6  # 
 7  # Contents: 
 8  #   QMTest DirRunDatabase class. 
 9  # 
10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from glob import glob 
21  import os.path 
22  from qm.test import base 
23  from qm.test.reader_test_run import ReaderTestRun 
24  from qm.test.run_database import RunDatabase 
25   
26  ######################################################################## 
27  # Classes 
28  ######################################################################## 
29   
30 -class DirRunDatabase(RunDatabase):
31 """A 'DirRunDatabase' reads test runs from a directory. 32 33 A 'DirRunDatabase' is associated with a given directory. The 34 database consists of all '.qmr' files in the directory. Each 35 '.qmr' file is treated as a result file.""" 36
37 - def __init__(self, directory, database):
38 """Create a new 'DirRunDatabase'. 39 40 'directory' -- The path to the directory containing the 41 results files. 42 43 'database' -- The test 'Database' to which the results files 44 correspond.""" 45 46 self.__runs = [] 47 # Read through all the .qmr files. 48 for f in glob(os.path.join(directory, "*.qmr")): 49 try: 50 # Create the ResultReader corresponding to f. 51 reader = base.load_results(f, database) 52 run = ReaderTestRun(reader) 53 except: 54 # If anything goes wrong reading the file, just skip 55 # it. 56 continue 57 # Add this run to the list. 58 self.__runs.append(run)
59 60
61 - def GetAllRuns(self):
62 63 return self.__runs
64

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.sql_result_stream-module.html0000664000076400007640000000303411122067144031524 0ustar stefanstefan sql_result_stream

Module sql_result_stream


Classes

SQLResultReader
SQLResultStream

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DTtestExpr-pysrc.html0000664000076400007640000004371211122067154031602 0ustar stefanstefan qm.external.DocumentTemplate.DTtestExpr
Package qm :: Package external :: Package DocumentTemplate :: Module DTtestExpr
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DTtestExpr

 1  ############################################################################## 
 2  # 
 3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
 4  # 
 5  # This software is subject to the provisions of the Zope Public License, 
 6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
 7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
 8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
10  # FOR A PARTICULAR PURPOSE 
11  # 
12  ############################################################################## 
13  __doc__='''short description 
14   
15   
16  $Id: DTtestExpr.py 1069 2008-11-13 21:55:43Z stefan $''' 
17  __version__='$Revision: 1069 $'[11:-2] 
18   
19  from DocumentTemplate import * 
20  import sys 
21   
22 -def test1():
23 print HTML('area code=<!--#var expr="phone[:3]"-->')(phone='7035551212')
24
25 -def test2():
26 print HTML('area code=<!--#var expr="phone.number"-->')(phone='7035551212')
27
28 -def test3():
29 print HTML('area code=<!--#var expr="phone*1000"-->')(phone='7035551212')
30
31 -def test4():
32 33 h=HTML( 34 """ 35 <!--#if expr="level==1"--> 36 level was 1 37 <!--#elif expr="level==2"--> 38 level was 2 39 <!--#elif expr="level==3"--> 40 level was 3 41 <!--#else--> 42 level was something else 43 <!--#endif--> 44 """) 45 46 for i in range(4): 47 print '-' * 77 48 print i, h(level=i) 49 print '-' * 77
50 51 52 if __name__ == "__main__": 53 try: command=sys.argv[1] 54 except: command='main' 55 globals()[command]() 56

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform.MailError-class.html0000664000076400007640000001532611122067146026127 0ustar stefanstefan qm.platform.MailError
Package qm :: Module platform :: Class MailError
[hide private]
[frames] | no frames]

Class MailError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  MailError

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.QMTestServer-class.html0000664000076400007640000025376211122067151027266 0ustar stefanstefan qm.test.web.web.QMTestServer
Package qm :: Package test :: Package web :: Module web :: Class QMTestServer
[hide private]
[frames] | no frames]

Class QMTestServer

source code

SocketServer.BaseServer --+                
                          |                
     SocketServer.TCPServer --+            
                              |            
      BaseHTTPServer.HTTPServer --+        
                                  |        
                     web.HTTPServer --+    
                                      |    
                          web.WebServer --+
                                          |
                                         QMTestServer

A 'QMTestServer' is the web GUI interface to QMTest.

Instance Methods [hide private]
 
__init__(self, database, port, address, log_file, targets, context, expectations, run_db)
Create and bind an HTTP server.
source code
 
GetContext(self)
Return the 'Context' in which tests will be run.
source code
 
GetDatabase(self)
Return the 'Database' handled by this server.
source code
 
GetRunDatabase(self)
Return the 'RunDatabase' handled by this server.
source code
 
GetExpectationDatabase(self)
Return the current ExpectationDatabase.
source code
 
GetExpectedOutcomes(self)
Return the current expected outcomes for the test database.
source code
 
GetHTMLClassForOutcome(self, outcome)
Return the CSS class for the 'outcome'.
source code
 
GetResultsStream(self)
Return the 'StorageResultsStream' containing test results.
source code
 
HandleClearResults(self, request)
Handle a request to clear the current test results.
source code
 
HandleCreateSuite(self, request)
Handle a submission of a new test suite.
source code
 
HandleDeleteItem(self, request)
Handle a request to delete a test or resource.
source code
 
HandleDeleteSuite(self, request)
Handle a request to delete a test suite.
source code
 
HandleDir(self, request)
Generate a directory page.
source code
 
HandleDirReport(self, request)
Generate a directory report page.
source code
 
HandleEditContext(self, request)
Handle a request to edit the context.
source code
 
HandleEditSuite(self, request)
Generate the page for editing a test suite.
source code
 
HandleLoadContext(self, request)
Handle a request to upload a context file.
source code
 
HandleLoadExpectations(self, request)
Handle a request to upload results.
source code
 
HandleLoadResults(self, request)
Handle a request to upload results.
source code
 
HandleNewResource(self, request)
Handle a request to create a new test.
source code
 
HandleNewTest(self, request)
Handle a request to create a new test.
source code
 
HandleNewSuite(self, request)
Handle a request to create a new suite.
source code
 
HandleRunTests(self, request)
Handle a request to run tests.
source code
 
HandleSaveContext(self, request)
Handlea request to save the context to a file.
source code
 
HandleSaveExpectations(self, request)
Handle a request to save expectations to a file.
source code
 
HandleSaveResults(self, request)
Handle a request to save results to a file.
source code
 
HandleSetExpectation(self, request)
Handle a request to set expectations.
source code
 
HandleShowItem(self, request)
Handle a request to show a test or resource.
source code
 
HandleShowResult(self, request)
Handle a request to show result detail.
source code
 
HandleShowResults(self, request)
Handle a request to show results.
source code
 
HandleShowItemReport(self, request)
Handle a request to show a test or resource report.
source code
 
HandleShowResultReport(self, request)
Handle a request to show result report.
source code
 
HandleShowSuite(self, request, edit=0)
Generate the page for displaying or editing a test suite.
source code
 
HandleShutdown(self, request)
Handle a request to shut down the server.
source code
 
HandleStopTests(self, request)
Handle a request to stop test execution.
source code
 
HandleSubmitContext(self, request)
Handle a context submission..
source code
 
HandleSubmitContextFile(self, request)
Handle a context file submission..
source code
 
HandleSubmitExpectation(self, request)
Handle setting a single expectation.
source code
 
HandleSubmitExpectations(self, request)
Handle uploading expected results.
source code
 
HandleSubmitExpectationsForm(self, request)
Handle uploading expected results.
source code
 
HandleSubmitItem(self, request)
Handle a test or resource submission.
source code
 
HandleSubmitResults(self, request)
Handle uploading results.
source code
 
HandleSubmitSuite(self, request)
Handle test suite submission.
source code
 
MakeNewTest(self, test_class_name, test_id)
Create a new test with default arguments.
source code
 
MakeNewResource(self, resource_class_name, resource_id)
Create a new resource with default arguments.
source code
 
_HandleRoot(self, request)
Handle the '/' URL.
source code
 
_ClosePopupAndRedirect(self, url)
Close the current window.
source code

Inherited from web.WebServer: Bind, CachePage, GetCachedPage, GetServerAddress, GetTemporaryAttachmentStore, HandleNoSessionError, IsScript, LogMessage, MakeButtonForCachedPopup, MakeConfirmationDialog, MakePopupDialog, ProcessScript, RegisterPathTranslation, RegisterScript, RequestShutdown, Run, TranslateRequest, handle_error

Inherited from web.WebServer (private): _HandleProblems

Inherited from web.HTTPServer: server_bind

Inherited from SocketServer.TCPServer: close_request, fileno, get_request, server_activate, server_close

Inherited from SocketServer.BaseServer: finish_request, handle_request, process_request, serve_forever, verify_request

Class Variables [hide private]

Inherited from BaseHTTPServer.HTTPServer: allow_reuse_address

Inherited from SocketServer.TCPServer: address_family, request_queue_size, socket_type

Method Details [hide private]

__init__(self, database, port, address, log_file, targets, context, expectations, run_db)
(Constructor)

source code 

Create and bind an HTTP server.

'database' -- The test database to serve.

'port' -- The port number on which to accept HTTP requests.

'address' -- The local address to which to bind the server. An empty string indicates all local addresses.

'log_file' -- A file object to which the server will log requests. 'None' for no logging.

'targets' -- A sequence of 'Target' objects to use when running tests.

'context' -- The 'Context' in which tests will execute.

Overrides: SocketServer.BaseServer.__init__

GetContext(self)

source code 

Return the 'Context' in which tests will be run.

returns -- The 'Context' in which tests will be run.

GetDatabase(self)

source code 

Return the 'Database' handled by this server.

returns -- The 'Database' handled by this server.

GetRunDatabase(self)

source code 

Return the 'RunDatabase' handled by this server.

returns -- The 'RunDatabase' handled by this server.

GetExpectationDatabase(self)

source code 

Return the current ExpectationDatabase.

returns -- The ExpectationDatabase instance.

GetExpectedOutcomes(self)

source code 

Return the current expected outcomes for the test database.

returns -- A map from test IDs to outcomes. Some tests may have not have an entry in the map.

GetHTMLClassForOutcome(self, outcome)

source code 

Return the CSS class for the 'outcome'.

'outcome' -- One of the result outcomes.

returns -- The name of a CSS class. These are used with <span> elements. See 'qm.css'.

GetResultsStream(self)

source code 

Return the 'StorageResultsStream' containing test results.

returns -- The 'StorageResultsStream' associated with this server.

HandleClearResults(self, request)

source code 

Handle a request to clear the current test results.

'request' -- A 'WebRequest' object.

HandleCreateSuite(self, request)

source code 

Handle a submission of a new test suite.

'request' -- A 'WebRequest' object.

HandleDeleteItem(self, request)

source code 

Handle a request to delete a test or resource.

This function handles the script requests 'delete-test' and 'delete-resource'.

'request' -- A 'WebRequest' object.

The ID of the test or resource to delete is specified in the 'id' field of the request.

HandleDeleteSuite(self, request)

source code 

Handle a request to delete a test suite.

'request' -- A 'WebRequest' object.

The ID of the suite to delete is specified in the 'id' field of the request.

HandleDir(self, request)

source code 

Generate a directory page.

'request' -- A 'WebRequest' object.

The request has these fields:

'path' -- A path in test/resource/suite ID space. If specified, only tests and resources in this subtree are displayed, and their IDs are displayed relative to this path. If omitted, the entire contents of the test database are shown.

HandleDirReport(self, request)

source code 

Generate a directory report page.

'request' -- A 'WebRequest' object.

The request has these fields:

'path' -- A path in test/resource/suite ID space. If specified, only tests and resources in this subtree are displayed, and their IDs are displayed relative to this path. If omitted, the entire contents of the test database are shown.

HandleEditContext(self, request)

source code 

Handle a request to edit the context.

'request' -- The 'WebRequest' that caused the event.

HandleLoadContext(self, request)

source code 

Handle a request to upload a context file.

'request' -- The 'WebRequest' that caused the event.

HandleLoadExpectations(self, request)

source code 

Handle a request to upload results.

'request' -- The 'WebRequest' that caused the event.

HandleLoadResults(self, request)

source code 

Handle a request to upload results.

'request' -- The 'WebRequest' that caused the event.

HandleNewResource(self, request)

source code 

Handle a request to create a new test.

'request' -- The 'WebRequest' that caused the event.

HandleNewTest(self, request)

source code 

Handle a request to create a new test.

'request' -- The 'WebRequest' that caused the event.

HandleNewSuite(self, request)

source code 

Handle a request to create a new suite.

'request' -- The 'WebRequest' that caused the event.

HandleRunTests(self, request)

source code 
Handle a request to run tests.

'request' -- The 'WebRequest' that caused the event.

These fields in 'request' are used:

  'ids' -- A comma-separated list of test and suite IDs.  These IDs
  are expanded into the list of IDs of tests to run.

HandleSaveContext(self, request)

source code 

Handlea request to save the context to a file.

'request' -- The 'WebRequest' that caused the event.

HandleSaveExpectations(self, request)

source code 

Handle a request to save expectations to a file.

'request' -- The 'WebRequest' that caused the event.

HandleSaveResults(self, request)

source code 

Handle a request to save results to a file.

'request' -- The 'WebRequest' that caused the event.

HandleSetExpectation(self, request)

source code 

Handle a request to set expectations.

'request' -- A 'WebRequest' object.

HandleShowItem(self, request)

source code 
Handle a request to show a test or resource.

'request' -- A 'WebRequest' object.

This function generates pages to handle these requests:

  'create-test' -- Generate a form for initial editing of a test
  about to be created, given its test ID and test class.

  'create-resource' -- Likewise for an resource.

  'show-test' -- Display a test.

  'show-resource' -- Likewise for an resource.

  'edit-test' -- Generate a form for editing an existing test.

  'edit-resource' -- Likewise for an resource.

This function distinguishes among these cases by checking the script
name of the request object.

The request must have the following fields:

  'id' -- A test or resource ID.  For show or edit pages, the ID of an
  existing item.  For create pages, the ID of the item being
  created.

  'class' -- For create pages, the name of the test or resource
  class.

HandleShowResult(self, request)

source code 

Handle a request to show result detail. If a 'test_run' argument was provided, fetch the result from the corresponding test run. Else read it from the results stream.

'request' -- The 'WebRequest' that caused the event.

HandleShowResults(self, request)

source code 

Handle a request to show results.

'request' -- The 'WebRequest' that caused the event.

HandleShowItemReport(self, request)

source code 
Handle a request to show a test or resource report.

'request' -- A 'WebRequest' object.

This function generates pages to handle these requests:

  'show-test' -- Display a test.

  'show-resource' -- Likewise for an resource.

This function distinguishes among these cases by checking the script
name of the request object.

The request must have the following fields:

  'id' -- A test or resource ID.  For show or edit pages, the ID of an
  existing item.  For create pages, the ID of the item being
  created.

HandleShowResultReport(self, request)

source code 

Handle a request to show result report.

'request' -- The 'WebRequest' that caused the event.

HandleShowSuite(self, request, edit=0)

source code 
Generate the page for displaying or editing a test suite.

'request' -- A 'WebRequest' object.

'edit' -- If true, display the page for editing the suite.
Otherwise, just display the suite.

The request has the following fields:

  'id' -- The ID of the suite to display or edit.

HandleShutdown(self, request)

source code 

Handle a request to shut down the server.

'request' -- The 'WebRequest' that caused the event.

HandleStopTests(self, request)

source code 

Handle a request to stop test execution.

'request' -- The 'WebRequest' that caused the event.

HandleSubmitContext(self, request)

source code 

Handle a context submission..

'request' -- The 'WebRequest' that caused the event. The 'request' must have a 'context_vars' key, whose value is the the context variables.

HandleSubmitContextFile(self, request)

source code 

Handle a context file submission..

'request' -- The 'WebRequest' that caused the event.

HandleSubmitExpectation(self, request)

source code 

Handle setting a single expectation.

'request' -- The 'WebRequest' that caused the event.

HandleSubmitExpectations(self, request)

source code 

Handle uploading expected results.

'request' -- The 'WebRequest' that caused the event.

HandleSubmitExpectationsForm(self, request)

source code 

Handle uploading expected results.

'request' -- The 'WebRequest' that caused the event.

HandleSubmitItem(self, request)

source code 

Handle a test or resource submission.

This function handles submission of the test or resource editing form generated by 'handle_show'. The script name in 'request' should be 'submit-test' or 'submit-resource'. It constructs the appropriate 'Test' or 'Resource' object and writes it to the database, either as a new item or overwriting an existing item.

The request must have the following form fields:

'id' -- The test or resource ID of the item being edited or created.

'class' -- The name of the test or resource class of this item.

arguments -- Argument values are encoded in fields whose names start with 'qm.fields.Field.form_field_prefix'.

HandleSubmitResults(self, request)

source code 

Handle uploading results.

'request' -- The 'WebRequest' that caused the event.

HandleSubmitSuite(self, request)

source code 
Handle test suite submission.

'request' -- A 'WebRequest' object.

The request object has these fields:

  'id' -- The ID of the test suite being edited.  If a suite with
  this ID exists, it is replaced (it must not be an implicit suite
  though).  Otherwise a new suite is edited.

  'test_ids' -- A comma-separated list of test IDs to include in the
  suite, relative to the suite's own ID.

  'suite_ids' -- A comma-separated list of other test suite IDs to
  include in the suite, relative to the suite's own ID.

MakeNewTest(self, test_class_name, test_id)

source code 

Create a new test with default arguments.

'test_class_name' -- The name of the test class of which to create a new test.

'test_id' -- The test ID of the new test.

returns -- A new 'TestDescriptor' object.

MakeNewResource(self, resource_class_name, resource_id)

source code 

Create a new resource with default arguments.

'resource_class_name' -- The name of the resource class of which to create a new resource.

'resource_id' -- The resource ID of the new resource.

returns -- A new 'ResourceDescriptor' object.

_HandleRoot(self, request)

source code 

Handle the '/' URL.

Overrides: web.WebServer._HandleRoot

_ClosePopupAndRedirect(self, url)

source code 

Close the current window. Redirect the main window to 'url'.

'url' -- A string giving the URL to which the main window should be redirected.

returns -- A string giving HTML that will close the current window and redirect the main window to 'url'.


qmtest-2.4.1/share/doc/qmtest/html/manual/help.html0000664000076400007640000002471711122067144021623 0ustar stefanstefan Help
 
[hide private]
[frames] | no frames]

API Documentation

This document contains the API (Application Programming Interface) documentation for this project. Documentation for the Python objects defined by the project is divided into separate pages for each package, module, and class. The API documentation also includes two pages containing information about the project as a whole: a trees page, and an index page.

Object Documentation

Each Package Documentation page contains:

  • A description of the package.
  • A list of the modules and sub-packages contained by the package.
  • A summary of the classes defined by the package.
  • A summary of the functions defined by the package.
  • A summary of the variables defined by the package.
  • A detailed description of each function defined by the package.
  • A detailed description of each variable defined by the package.

Each Module Documentation page contains:

  • A description of the module.
  • A summary of the classes defined by the module.
  • A summary of the functions defined by the module.
  • A summary of the variables defined by the module.
  • A detailed description of each function defined by the module.
  • A detailed description of each variable defined by the module.

Each Class Documentation page contains:

  • A class inheritance diagram.
  • A list of known subclasses.
  • A description of the class.
  • A summary of the methods defined by the class.
  • A summary of the instance variables defined by the class.
  • A summary of the class (static) variables defined by the class.
  • A detailed description of each method defined by the class.
  • A detailed description of each instance variable defined by the class.
  • A detailed description of each class (static) variable defined by the class.

Project Documentation

The Trees page contains the module and class hierarchies:

  • The module hierarchy lists every package and module, with modules grouped into packages. At the top level, and within each package, modules and sub-packages are listed alphabetically.
  • The class hierarchy lists every class, grouped by base class. If a class has more than one base class, then it will be listed under each base class. At the top level, and under each base class, classes are listed alphabetically.

The Index page contains indices of terms and identifiers:

  • The term index lists every term indexed by any object's documentation. For each term, the index provides links to each place where the term is indexed.
  • The identifier index lists the (short) name of every package, module, class, method, function, variable, and parameter. For each identifier, the index provides a short description, and a link to its documentation.

The Table of Contents

The table of contents occupies the two frames on the left side of the window. The upper-left frame displays the project contents, and the lower-left frame displays the module contents:

Project
Contents
...
API
Documentation
Frame


Module
Contents
 
...
 

The project contents frame contains a list of all packages and modules that are defined by the project. Clicking on an entry will display its contents in the module contents frame. Clicking on a special entry, labeled "Everything," will display the contents of the entire project.

The module contents frame contains a list of every submodule, class, type, exception, function, and variable defined by a module or package. Clicking on an entry will display its documentation in the API documentation frame. Clicking on the name of the module, at the top of the frame, will display the documentation for the module itself.

The "frames" and "no frames" buttons below the top navigation bar can be used to control whether the table of contents is displayed or not.

The Navigation Bar

A navigation bar is located at the top and bottom of every page. It indicates what type of page you are currently viewing, and allows you to go to related pages. The following table describes the labels on the navigation bar. Note that not some labels (such as [Parent]) are not displayed on all pages.

Label Highlighted when... Links to...
[Parent] (never highlighted) the parent of the current package
[Package] viewing a package the package containing the current object
[Module] viewing a module the module containing the current object
[Class] viewing a class the class containing the current object
[Trees] viewing the trees page the trees page
[Index] viewing the index page the index page
[Help] viewing the help page the help page

The "show private" and "hide private" buttons below the top navigation bar can be used to control whether documentation for private objects is displayed. Private objects are usually defined as objects whose (short) names begin with a single underscore, but do not end with an underscore. For example, "_x", "__pprint", and "epydoc.epytext._tokenize" are private objects; but "re.sub", "__init__", and "type_" are not. However, if a module defines the "__all__" variable, then its contents are used to decide which objects are private.

A timestamp below the bottom navigation bar indicates when each page was last updated.

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_database.ExtensionDatabase-class.html0000664000076400007640000014325711122067150031531 0ustar stefanstefan qm.test.file_database.ExtensionDatabase
Package qm :: Package test :: Module file_database :: Class ExtensionDatabase
[hide private]
[frames] | no frames]

Class ExtensionDatabase

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      database.Database --+    
                          |    
               FileDatabase --+
                              |
                             ExtensionDatabase

An 'ExtensionDatabase' is a 'FileDatabase' where each kind of entity (test, suite, resource) has a particular extension. For example, if tests have the extension '.qmt', then all files ending with '.qmt' are considered tests. If an extension for a particular kind of entity is not specified or is the empty string, then all files will be considered to be that kind of entity.

'ExtensionDatabase' is an abstract class.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, path, arguments=None, **args)
Construct a 'Database'.
source code
 
GetTestExtension(self)
Return the extension that indicates a file is a test.
source code
 
GetSuiteExtension(self)
Return the extension that indicates a file is a suite.
source code
 
GetResourceExtension(self)
Return the extension that indicates a file is a resource.
source code
 
GetTestPath(self, test_id)
Return the file containing 'test_id'.
source code
 
_IsTestFile(self, path)
Returns true if 'path' is a test file.
source code
 
GetSuitePath(self, suite_id)
Return the file containing 'suite_id'.
source code
 
_IsSuiteFile(self, path)
Returns true if 'path' is a test suite file or directory.
source code
 
GetResourcePath(self, resource_id)
Return the file containing 'resource_id'.
source code
 
_IsResourceFile(self, path)
Returns true if 'path' is a resource file.
source code
 
_GetPathFromLabel(self, label)
Returns the file system path corresponding to 'label'.
source code
 
_GetLabelFromBasename(self, basename)
Returns the label associated with a file named 'basename'.
source code
 
_GetRelativeLabelPath(self, label)
Returns a representation of 'label' as a filename.
source code

Inherited from FileDatabase: GetIds, GetResource, GetRoot, GetSubdirectories, GetSuite, GetTest, RemoveExtension

Inherited from database.Database: ExpandIds, GetAttachmentStore, GetClassPaths, GetConfigurationDirectory, GetExtension, GetExtensions, GetItem, GetLabelComponents, GetPath, GetResourceClassNames, GetResourceIds, GetSuiteIds, GetTestClassNames, GetTestIds, HasResource, HasSuite, HasTest, IsModifiable, IsValidLabel, JoinLabels, SplitLabel, SplitLabelLeft, WriteExtension

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.fields.TextField'> test_extension>, <...
A list of the arguments to the extension class.
  _argument_dictionary = {'label_class': <<class 'qm.fields.Text...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.TextField'> resource_exte...
A list of all the 'Field's in this class.
  resource_extension = '.qma'
  suite_extension = '.qms'
  test_extension = '.qmt'

Inherited from database.Database: ITEM_KINDS, RESOURCE, SUITE, TEST, kind, label_class, modifiable

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, path, arguments=None, **args)
(Constructor)

source code 

Construct a 'Database'.

'path' -- A string containing the absolute path to the directory containing the database.

'arguments' -- A dictionary mapping attribute names to values. The use of this parameter is deprecated. Use keyword arguments instead.

Derived classes must call this method from their own '__init__' methods. Every derived class must have an '__init__' method that takes the path to the directory containing the database as its only argument. The path provided to the derived class '__init__' function will always be an absolute path.

Overrides: object.__init__
(inherited documentation)

GetTestExtension(self)

source code 

Return the extension that indicates a file is a test.

returns -- The extension (including the leading period) that indicates that a file is a test.

GetSuiteExtension(self)

source code 

Return the extension that indicates a file is a suite.

returns -- The extension (including the leading period) that indicates that a file is a suite.

GetResourceExtension(self)

source code 

Return the extension that indicates a file is a resource.

returns -- The extension (including the leading period) that indicates that a file is a resource.

GetTestPath(self, test_id)

source code 

Return the file containing 'test_id'.

'test_id' -- The name of a test.

returns -- The absolute file name of the file that contains, or would contain, 'test_id'. This method works even if no test named 'test_id' exists.

Derived classes may override this method.

Overrides: FileDatabase.GetTestPath
(inherited documentation)

_IsTestFile(self, path)

source code 

Returns true if 'path' is a test file.

'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels.

returns -- True iff the file corresponds to a test.

Derived classes must override this method.

Overrides: FileDatabase._IsTestFile
(inherited documentation)

GetSuitePath(self, suite_id)

source code 

Return the file containing 'suite_id'.

'suite_id' -- The name of a suite.

returns -- The absolute file name of the file (or directory) that contains, or would contain, 'suite_id'. This method works even if no suite named 'suite_id' exists.

Derived classes may override this method.

Overrides: FileDatabase.GetSuitePath
(inherited documentation)

_IsSuiteFile(self, path)

source code 

Returns true if 'path' is a test suite file or directory.

'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels.

returns -- True iff the file corresponds to a test.

Derived classes may override this method, but only to restrict the set of suites. In particular, a derived class method may return false where this method would return true, but never vice versa.

Derived classes must override this method.

Overrides: FileDatabase._IsSuiteFile
(inherited documentation)

GetResourcePath(self, resource_id)

source code 

Return the file containing 'resource_id'.

'resource_id' -- The name of a resource.

returns -- The absolute file name of the file that contains, or would contain, 'resource_id'. This method works even if no Resource named 'resource_id' exists.

Derived classes may override this method.

Overrides: FileDatabase.GetResourcePath
(inherited documentation)

_IsResourceFile(self, path)

source code 

Returns true if 'path' is a resource file.

'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels.

returns -- True iff the file corresponds to a resource.

Derived classes must override this method.

Overrides: FileDatabase._IsResourceFile
(inherited documentation)

_GetPathFromLabel(self, label)

source code 

Returns the file system path corresponding to 'label'.

'label' -- The id for a test, test suite, or similar entity.

returns -- The absolute path for the corresponding entry in the file system, but without any required extension.

Overrides: FileDatabase._GetPathFromLabel
(inherited documentation)

_GetLabelFromBasename(self, basename)

source code 

Returns the label associated with a file named 'basename'.

'basename' -- The basename of a file, including the extension.

returns -- The corresponding label.

Derived classes may override this method.

Overrides: FileDatabase._GetLabelFromBasename
(inherited documentation)

_GetRelativeLabelPath(self, label)

source code 

Returns a representation of 'label' as a filename.

returns -- A filename corresponding to 'label'.

Overrides: FileDatabase._GetRelativeLabelPath

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[<<class 'qm.fields.TextField'> test_extension>,
 <<class 'qm.fields.TextField'> suite_extension>,
 <<class 'qm.fields.TextField'> resource_extension>]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'label_class': <<class 'qm.fields.TextField'> label_class>,
 'modifiable': <<class 'qm.fields.BooleanField'> modifiable>,
 'resource_extension': <<class 'qm.fields.TextField'> resource_extensi\
on>,
 'suite_extension': <<class 'qm.fields.TextField'> suite_extension>,
 'test_extension': <<class 'qm.fields.TextField'> test_extension>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.TextField'> resource_extension>,
 <<class 'qm.fields.BooleanField'> modifiable>,
 <<class 'qm.fields.TextField'> test_extension>,
 <<class 'qm.fields.TextField'> label_class>,
 <<class 'qm.fields.TextField'> suite_extension>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Util-module.html0000664000076400007640000010311311122067145031155 0ustar stefanstefan qm.external.DocumentTemplate.DT_Util
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Util
[hide private]
[frames] | no frames]

Module DT_Util

source code

DTML Utilities

$Id: DT_Util.py 1069 2008-11-13 21:55:43Z stefan $

Classes [hide private]
  Eval
Functions [hide private]
 
html_quote(v, name='(Unknown name)', md={}, character_entities=(('&', '&amp;'), ('<', '&lt;'), ('>', '&gt;'), ('"', '&quot;'))) source code
 
int_param(params, md, name, default=0, st=<type 'str'>) source code
 
careful_getattr(md, inst, name, default=[]) source code
 
careful_hasattr(md, inst, name) source code
 
careful_getitem(md, mapping, key) source code
 
careful_getslice(md, seq, *indexes) source code
 
careful_range(md, iFirst, *args) source code
 
careful_pow(self, x, y, z) source code
 
test(self, *args) source code
 
obsolete_attr(self, inst, name, md) source code
 
namespace(self, **kw)
Create a tuple consisting of a single instance whose attributes are provided as keyword arguments.
source code
 
render(self, v)
Render an object in the way done by the 'name' attribute
source code
 
name_param(params, tag='', expr=0, attr='name', default_unnamed=1) source code
 
parse_params(text, result=None, tag='', unparmre=re.compile(r'([\x00- ]*([^\x00- ="]+))'), qunparmre=re.compile(r'([\x00- ]*("[^"]*"))'), parmre=re.compile(r'([\x00- ]*([^\x00- ="]+)=([^\x00- ="]+))'), qparmre=re.compile(r'([\x00- ]*([^\x00- ="]+)="([^"]*)")'), **parms)
Parse tag parameters
source code
Variables [hide private]
  ParseError = 'Document Template Parse Error'
  ValidationError = 'Unauthorized'
  _marker = []
  d = {'None': None, '__call__': <function __call__ at 0x7f00bca...
  expr_globals = {'__builtins__': {}, '__guarded_getattr__': <fu...
  Expr_doc = '\n\n\nPython expression support\n\n Several docum...
  name = 'str'
Function Details [hide private]

parse_params(text, result=None, tag='', unparmre=re.compile(r'([\x00- ]*([^\x00- ="]+))'), qunparmre=re.compile(r'([\x00- ]*("[^"]*"))'), parmre=re.compile(r'([\x00- ]*([^\x00- ="]+)=([^\x00- ="]+))'), qparmre=re.compile(r'([\x00- ]*([^\x00- ="]+)="([^"]*)")'), **parms)

source code 

Parse tag parameters

The format of tag parameters consists of 1 or more parameter specifications separated by whitespace. Each specification consists of an unnamed and unquoted value, a valueless name, or a name-value pair. A name-value pair consists of a name and a quoted or unquoted value separated by an '='.

The input parameter, text, gives the text to be parsed. The keyword parameters give valid parameter names and default values.

If a specification is not a name-value pair and it is not the first specification and it is a valid parameter name, then it is treated as a name-value pair with a value as given in the keyword argument. Otherwise, if it is not a name-value pair, it is treated as an unnamed value.

The data are parsed into a dictionary mapping names to values. Unnamed values are mapped from the name '""'. Only one value may be given for a name and there may be only one unnamed value.


Variables Details [hide private]

d

Value:
TemplateDict.__dict__

expr_globals

Value:
{'__builtins__': {}, '__guarded_mul__': VSEval.careful_mul, '__guarded\
_getattr__': careful_getattr, '__guarded_getitem__': careful_getitem, \
'__guarded_getslice__': careful_getslice,}

Expr_doc

Value:
'''


Python expression support

  Several document template tags, including \'var\', \'in\', \'if\', \\
'else\',
  and \'elif\' provide support for using Python expressions via an
...

././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test_database.CompilationTest-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test_database.CompilationTest-0000664000076400007640000004365011122067147033351 0ustar stefanstefan qm.test.classes.compilation_test_database.CompilationTest
Package qm :: Package test :: Package classes :: Module compilation_test_database :: Class CompilationTest
[hide private]
[frames] | no frames]

Class CompilationTest

source code

         object --+                    
                  |                    
extension.Extension --+                
                      |                
      runnable.Runnable --+            
                          |            
                  test.Test --+        
                              |        
 compiler_test.CompilerBase --+        
                              |        
     compiler_test.CompilerTest --+    
                                  |    
   compilation_test.CompilationTest --+
                                      |
                                     CompilationTest

A CompilationTest fetches compilation parameters from environment variables CPPFLAGS, <lang>_options, and <lang>_ldflags in addition to the CompilerTable-related parameters.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
_GetCompilationSteps(self, c)
Return the compilation steps for this test.
source code

Inherited from compilation_test.CompilationTest: Run

Inherited from compilation_test.CompilationTest (private): _CheckOutput, _GetCompiler, _GetTarget, _IsExecutionRequired

Inherited from compiler_test.CompilerTest (private): _CheckExecutableOutput, _DiagnosticsToString, _GetAnnotationPrefix, _GetExecutableArguments, _GetLibraryDirectories, _IsDiagnosticExpected, _MustExecutableExitSuccessfully, _RunExecutable

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Inherited from compiler_test.CompilerBase (private): _GetDirectory, _GetObjectFileName, _MakeDirectory, _RemoveDirectory

Class Variables [hide private]
  options = SetField(TextField(), computed= "true")
  ldflags = SetField(TextField(), computed= "true")
  source_files = SetField(TextField(), computed= "true")
  executable = TextField(computed= "true")
  language = TextField()

Inherited from compilation_test.CompilationTest: execute

Inherited from compiler_test.CompilerTest (private): _ignored_diagnostic_regexps

Inherited from test.Test: PREREQUISITES_FIELD_ID, arguments, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

_GetCompilationSteps(self, c)

source code 

Return the compilation steps for this test.

'context' -- The 'Context' in which this test is being executed.

returns -- A sequence of 'CompilationStep' objects.

Overrides: compiler_test.CompilerTest._GetCompilationSteps
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python_label-pysrc.html0000664000076400007640000003760411122067163027537 0ustar stefanstefan qm.test.classes.python_label
Package qm :: Package test :: Package classes :: Module python_label
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.python_label

 1  ######################################################################## 
 2  # 
 3  # File:   python_label.py 
 4  # Author: Mark Mitchell 
 5  # Date:   06/11/2002 
 6  # 
 7  # Contents: 
 8  #   PythonLabel 
 9  # 
10  # Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ######################################################################## 
17   
18  from   qm.label   import * 
19  import re 
20   
21  ######################################################################## 
22  # Classes 
23  ######################################################################## 
24   
25 -class PythonLabel(Label):
26 """A 'PythonLabel' is a 'Label' that uses the 'a.b.c' naming scheme. 27 28 A 'PythonLabel' is a 'Label' whose separator character is the period 29 and whose components consist of lower-case letters, numerals, and 30 underscores. These labels have the property that they can be easily 31 mapped to filenames on most operating systems; all valid labels are 32 valid filenames (replacing '.' with '/') and two different labels 33 will always map to two different filenames.""" 34 35 _sep = '.' 36 """The separator character used to separate components.""" 37 38 __valid_label_regexp = re.compile("[-a-z0-9_%s]+$" % _sep) 39 """A compiled regular expression that matches valid labels.""" 40
41 - def IsValid(self, label, is_component):
42 """Returns true if this label is not valid. 43 44 returns -- True if this label is not valid.""" 45 46 if not Label.IsValid(self, label, is_component): 47 # If the label does not meet the basic validity 48 # requirements, reject it. 49 return 0 50 elif not self.__valid_label_regexp.match(label): 51 # If the label contains invalid characters, reject it. 52 return 0 53 54 return 1
55

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test-module.html0000664000076400007640000002114211122067145030547 0ustar stefanstefan qm.test.classes.compilation_test
Package qm :: Package test :: Package classes :: Module compilation_test
[hide private]
[frames] | no frames]

Module compilation_test

source code

Classes [hide private]
  CompilationTest
A CompilationTest compiles and optionally runs an executable.
  CompiledResource
A CompiledResource compiles an executable.
  ExecutableTest
An ExecuableTest runs an executable from a CompiledResource.
Functions [hide private]
 
_get_host(context, variable)
Get a host instance according to a particular context variable.
source code
Function Details [hide private]

_get_host(context, variable)

source code 

Get a host instance according to a particular context variable. Return a default 'LocalHost' host if the variable is undefined.

'context' -- The context to read the host descriptor from.

'variable' -- The name to which the host descriptor is bound.

returns -- A Host instance.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_InSV-module.html0000664000076400007640000002315511122067145031066 0ustar stefanstefan qm.external.DocumentTemplate.DT_InSV
Package qm :: Package external :: Package DocumentTemplate :: Module DT_InSV
[hide private]
[frames] | no frames]

Module DT_InSV

source code

Sequence variables support

$Id: DT_InSV.py 1069 2008-11-13 21:55:43Z stefan $


Version: 1069

Classes [hide private]
  sequence_variables
Functions [hide private]
 
sub(s1, s2, src) source code
 
opt(start, end, size, orphan, sequence) source code
Variables [hide private]
  __doc__ = '''Sequence variables supp...
  mv = None
Variables Details [hide private]

__doc__

Value:
'''Sequence variables support


$Id: DT_InSV.py 1069 2008-11-13 21:55:43Z stefan $'''

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_engine-pysrc.html0000664000076400007640000102102411122067152026737 0ustar stefanstefan qm.test.execution_engine
Package qm :: Package test :: Module execution_engine
[hide private]
[frames] | no frames]

Source Code for Module qm.test.execution_engine

  1  ######################################################################## 
  2  # 
  3  # File:   execution_engine.py 
  4  # Author: Mark Mitchell 
  5  # Date:   01/02/2002 
  6  # 
  7  # Contents: 
  8  #   ExecutionEngine 
  9  # 
 10  # Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import os 
 21  import qm.common 
 22  import qm.queue 
 23  from   qm.test.base import * 
 24  import qm.test.cmdline 
 25  import qm.test.database 
 26  from   qm.test.expectation_database import ExpectationDatabase 
 27  from   qm.test.context import * 
 28  import qm.xmlutil 
 29  from   result import * 
 30  import select 
 31  import sys 
 32  import time 
 33   
 34  ######################################################################## 
 35  # Classes 
 36  ######################################################################## 
 37   
38 -class TerminationRequested(qm.common.QMException):
39 """A target requested termination of the test loop.""" 40 41 pass
42 43 44
45 -class ExecutionEngine:
46 """A 'ExecutionEngine' executes tests. 47 48 A 'ExecutionEngine' object handles the execution of a collection 49 of tests. 50 51 This class schedules the tests across one or more targets. 52 53 The shedule is determined dynamically as the tests are executed 54 based on which targets are idle and which are not. Therefore, the 55 testing load should be reasonably well balanced, even across a 56 heterogeneous network of testing machines.""" 57 58
59 - class __TestStatus(object):
60 """A '__TestStatus' indicates whether or not a test has been run. 61 62 The 'outcome' slot indicates whether the test has not be queued so 63 that it can be run, has completed, or has not been processed at all. 64 65 If there are tests that have this test as a prerequisite, they are 66 recorded in the 'dependants' slot. 67 68 Ever test passes through the following states, in the following 69 order: 70 71 1. Initial 72 73 A test in this state has not yet been processed. In this state, 74 the 'outcome' slot is 'None'. 75 76 2. Queued 77 78 A test in this state has been placed on the stack of tests 79 waiting to run. In this state, the 'outcome' slot is 80 'QUEUED'. Such a test may be waiting for prerequisites to 81 complete before it can run. 82 83 3. Ready 84 85 A test in this state is ready to run. All prerequisites have 86 completed, and their outcomes were as expected. In this 87 state, the 'outcome' slot is 'READY'. 88 89 4. Finished 90 91 A test in this state has finished running. In this state, the 92 'outcome' slot is one of the 'Result.outcomes'. 93 94 The only exception to this order is that when an error is noted 95 (like a failure to load a test from the database, or a 96 prerequisite has an unexpected outcome) a test may jump to the 97 "finished" state without passing through intermediate states.""" 98 99 __slots__ = "outcome", "dependants" 100 101 QUEUED = "QUEUED" 102 READY = "READY" 103
104 - def __init__(self):
105 106 self.outcome = None 107 self.dependants = None
108 109
110 - def GetState(self):
111 """Return the state of this test. 112 113 returns -- The state of this test, using the representation 114 documented above.""" 115 116 return self.outcome
117 118
119 - def NoteQueued(self):
120 """Place the test into the "queued" state.""" 121 122 assert self.outcome is None 123 self.outcome = self.QUEUED
124 125
126 - def HasBeenQueued(self):
127 """Returns true if the test was ever queued. 128 129 returns -- True if the test has ever been on the queue. 130 Such a test may be ready to run, or may in fact have already 131 run to completion.""" 132 133 return self.outcome == self.QUEUED or self.HasBeenReady()
134 135
136 - def NoteReady(self):
137 """Place the test into the "ready" state.""" 138 139 assert self.outcome is self.QUEUED 140 self.outcome = self.READY
141 142
143 - def HasBeenReady(self):
144 """Returns true if the test was ever ready. 145 146 returns -- True if the test was every ready to run. Such a 147 test may have already run to completion.""" 148 149 return self.outcome == self.READY or self.IsFinished()
150 151
152 - def IsFinished(self):
153 """Returns true if the test is in the "finished" state. 154 155 returns -- True if this test is in the "finished" state.""" 156 157 return not (self.outcome is None 158 or self.outcome is self.READY 159 or self.outcome is self.QUEUED)
160 161
162 - def NoteDependant(self, test_id):
163 """Note that 'test_id' depends on 'self'. 164 165 'test_id' -- The name of a test. That test has this test as a 166 prerequisite.""" 167 168 if self.dependants is None: 169 self.dependants = [test_id] 170 else: 171 self.dependants.append(test_id)
172 173 174 # Every target is in one of three states: busy, idle, or starving. 175 # A busy target is running tests, an idle target is ready to run 176 # tests, and a starving target is ready to run tests, but no tests 177 # are available for it to run. 178 __TARGET_IDLE = "IDLE" 179 __TARGET_BUSY = "BUSY" 180 __TARGET_STARVING = "STARVING" 181 182
183 - def __init__(self, 184 database, 185 test_ids, 186 context, 187 targets, 188 result_streams = None, 189 expectations = None):
190 """Set up a test run. 191 192 'database' -- The 'Database' containing the tests that will be 193 run. 194 195 'test_ids' -- A sequence of IDs of tests to run. Where 196 possible, the tests are started in the order specified. 197 198 'context' -- The context object to use when running tests. 199 200 'targets' -- A sequence of 'Target' objects, representing 201 targets on which tests may be run. 202 203 'result_streams' -- A sequence of 'ResultStream' objects. Each 204 stream will be provided with results as they are available. 205 206 'expectations' -- If not 'None', an ExpectationDatabase object.""" 207 208 self.__database = database 209 self.__test_ids = test_ids 210 self.__context = context 211 self.__targets = targets 212 if result_streams is not None: 213 self.__result_streams = result_streams 214 else: 215 self.__result_streams = [] 216 if expectations is not None: 217 self.__expectations = expectations 218 else: 219 self.__expectations = ExpectationDatabase(test_database = database) 220 221 # There are no input handlers. 222 self.__input_handlers = {} 223 224 # There are no responses from the targets yet. 225 self.__response_queue = qm.queue.Queue(0) 226 # There no pending or ready tests yet. 227 self.__running = 0 228 229 self.__any_unexpected_outcomes = 0 230 231 # Termination has not yet been requested. 232 self.__terminated = 0
233 234
235 - def RequestTermination(self):
236 """Request that the execution engine stop executing tests. 237 238 Request that the execution thread be terminated. Termination 239 may take some time; tests that are already running will continue 240 to run, for example.""" 241 242 self._Trace("Test loop termination requested.") 243 self.__terminated = 1
244 245
246 - def _IsTerminationRequested(self):
247 """Returns true if termination has been requested. 248 249 returns -- True if no further tests should be executed. If the 250 value is -1, the execution engine should simply terminate 251 gracefully.""" 252 253 return self.__terminated
254 255
256 - def Run(self):
257 """Run the tests. 258 259 This method runs the tests specified in the __init__ 260 function. 261 262 returns -- True if any tests had unexpected outcomes.""" 263 264 # Write out run metadata. 265 self._WriteInitialAnnotations() 266 267 # Start all of the targets. 268 for target in self.__targets: 269 target.Start(self.__response_queue, self) 270 271 # Run all of the tests. 272 self._Trace("Starting test loop") 273 try: 274 try: 275 self._RunTests() 276 except: 277 self._Trace("Test loop exited with exception: %s" 278 % str(sys.exc_info())) 279 for rs in self.__result_streams: 280 rs.WriteAnnotation("qmtest.run.aborted", "true") 281 raise 282 finally: 283 self._Trace("Test loop finished.") 284 285 # Stop the targets. 286 self._Trace("Stopping targets.") 287 for target in self.__targets: 288 target.Stop() 289 290 # Read responses until there are no more. 291 self._Trace("Checking for final responses.") 292 while self.__CheckForResponse(wait=0): 293 pass 294 295 # Let all of the result streams know that the test run is 296 # complete. 297 end_time_str = qm.common.format_time_iso() 298 for rs in self.__result_streams: 299 rs.WriteAnnotation("qmtest.run.end_time", end_time_str) 300 rs.Summarize() 301 302 return self.__any_unexpected_outcomes
303 304
305 - def AddInputHandler(self, fd, function):
306 """Add an input handler for 'fd'. 307 308 'fd' -- A file descriptor, open for reading. 309 310 'function' -- A callable object taking a single parameter. 311 312 The execution engine will periodically monitor 'fd'. When input 313 is available, it will call 'function' passing it 'fd'.""" 314 315 self.__input_handlers[fd] = function
316 317
318 - def _RunTests(self):
319 320 num_tests = len(self.__test_ids) 321 322 # No tests have been started yet. 323 self.__num_tests_started = 0 324 325 self.__tests_iterator = iter(self.__test_ids) 326 327 # A map from the tests we are supposed to run to their current 328 # status. 329 self.__statuses = {} 330 for id in self.__test_ids: 331 self.__statuses[id] = self.__TestStatus() 332 333 # A stack of tests. If a test has prerequisites, the 334 # prerequisites will appear nearer to the top of the stack. 335 self.__test_stack = [] 336 # A hash-table giving the names of the tests presently on the 337 # stack. The names are the keys; the values are unused. 338 self.__ids_on_stack = {} 339 340 # All targets are initially idle. 341 self.__target_state = {} 342 for target in self.__targets: 343 self.__target_state[target] = self.__TARGET_IDLE 344 self.__has_idle_targets = 1 345 346 # Figure out what target groups are available. 347 self.__target_groups = {} 348 for target in self.__targets: 349 self.__target_groups[target.GetGroup()] = None 350 self.__target_groups = self.__target_groups.keys() 351 352 # A hash-table indicating whether or not a particular target 353 # pattern is matched by any of our targets. 354 self.__pattern_ok = {} 355 # A map from target groups to patterns satisfied by the group. 356 self.__patterns = {} 357 # A map from target patterns to lists of test descriptors ready 358 # to run. 359 self.__target_pattern_queues = {} 360 361 while self.__num_tests_started < num_tests: 362 # If the user interrupted QMTest, stop executing tests. 363 if self._IsTerminationRequested(): 364 self._Trace("Terminating test loop as requested.") 365 raise TerminationRequested, "Termination requested." 366 367 # Process any responses and update the count of idle targets. 368 while self.__CheckForResponse(wait=0): 369 pass 370 371 # Now look for idle targets. 372 if not self.__has_idle_targets: 373 # Block until one of the running tests completes. 374 self._Trace("All targets are busy -- waiting.") 375 self.__CheckForResponse(wait=1) 376 self._Trace("Response received.") 377 continue 378 379 # Go through each of the idle targets, finding work for it 380 # to do. 381 self.__has_idle_targets = 0 382 for target in self.__targets: 383 if self.__target_state[target] != self.__TARGET_IDLE: 384 continue 385 # Try to find work for the target. If there is no 386 # available work, the target is starving. 387 if not self.__FeedTarget(target): 388 self.__target_state[target] = self.__TARGET_STARVING 389 else: 390 # We gave the target some work, which may have 391 # changed its idle state, so update the status. 392 if target.IsIdle(): 393 self.__target_state[target] = self.__TARGET_IDLE 394 self.__has_idle_targets = 1 395 else: 396 self.__target_state[target] = self.__TARGET_BUSY 397 398 # Now every test that we're going to start has started; we just 399 # have wait for them all to finish. 400 self._Trace("Waiting for remaining tests to finish.") 401 while self.__running: 402 self.__CheckForResponse(wait=1)
403 404
405 - def __FeedTarget(self, target):
406 """Run a test on 'target' 407 408 'target' -- The 'Target' on which the test should be run. 409 410 returns -- True, iff a test could be found to run on 'target'. 411 False otherwise.""" 412 413 self._Trace("Looking for a test for target %s" % target.GetName()) 414 415 # See if there is already a ready-to-run test for this target. 416 for pattern in self.__patterns.get(target.GetGroup(), []): 417 tests = self.__target_pattern_queues.get(pattern, []) 418 if tests: 419 descriptor = tests.pop() 420 break 421 else: 422 # There was no ready-to-run test queued, so try to find one 423 # another one. 424 descriptor = self.__FindRunnableTest(target) 425 if descriptor is None: 426 # There really are no more tests ready to run. 427 return 0 428 429 target_name = target.GetName() 430 test_id = descriptor.GetId() 431 self._Trace("Running %s on %s" % (test_id, target_name)) 432 assert self.__statuses[test_id].GetState() == self.__TestStatus.READY 433 self.__num_tests_started += 1 434 self.__running += 1 435 target.RunTest(descriptor, self.__context) 436 return 1
437 438
439 - def __FindRunnableTest(self, target):
440 """Return a test that is ready to run. 441 442 'target' -- The 'Target' on which the test will run. 443 444 returns -- the 'TestDescriptor' for the next available ready 445 test, or 'None' if no test could be found that will run on 446 'target'. 447 448 If a test with unsatisfied prerequisites is encountered, the 449 test will be pushed on the stack and the prerequisites processed 450 recursively.""" 451 452 while 1: 453 if not self.__test_stack: 454 # We ran out of prerequisite tests, so pull a new one 455 # off the user's list. 456 try: 457 test_id = self.__tests_iterator.next() 458 except StopIteration: 459 # We're entirely out of fresh tests; give up. 460 return None 461 if self.__statuses[test_id].HasBeenQueued(): 462 # This test has already been handled (probably 463 # because it's a prereq of a test already seen). 464 continue 465 # Try to add the new test to the stack. 466 if not self.__AddTestToStack(test_id): 467 # If that failed, look for another test. 468 continue 469 self._Trace("Added new test %s to stack" % test_id) 470 471 descriptor, prereqs = self.__test_stack[-1] 472 # First look at the listed prereqs. 473 if prereqs: 474 new_test_id = prereqs.pop() 475 # We must filter tests that are already in the process 476 # here; if we were to do it earlier, we would be in 477 # danger of being confused by dependency graphs like 478 # A->B, A->C, B->C, where we can't know ahead of time 479 # that A's dependence on C is unnecessary. 480 if self.__statuses[new_test_id].HasBeenQueued(): 481 # This one is already in process. This might 482 # indicate a dependency cycle, so check for that 483 # now. 484 if new_test_id in self.__ids_on_stack: 485 self._Trace("Cycle detected (%s)" 486 % (new_test_id,)) 487 self.__AddUntestedResult \ 488 (new_test_id, 489 qm.message("dependency cycle")) 490 continue 491 else: 492 self.__AddTestToStack(new_test_id) 493 continue 494 else: 495 # Remove the test from the stack. 496 test_id = descriptor.GetId() 497 del self.__ids_on_stack[test_id] 498 self.__test_stack.pop() 499 500 # Check to see if the test is already ready to run, or 501 # has completed. The first case occurs when the test 502 # has prerequisites that have completed after it was 503 # placed on the stack; the second occurs when a test 504 # is marked UNTESTED after a cycle is detected. 505 if self.__statuses[test_id].HasBeenReady(): 506 continue 507 508 # Now check the prerequisites. 509 prereqs = self.__GetPendingPrerequisites(descriptor) 510 # If one of the prerequisites failed, the test will have 511 # been marked UNTESTED. Keep looking for a runnable 512 # test. 513 if prereqs is None: 514 continue 515 # If there are prerequisites, request notification when 516 # they have completed. 517 if prereqs: 518 for p in prereqs: 519 self.__statuses[p].NoteDependant(test_id) 520 # Keep looking for a runnable test. 521 continue 522 523 # This test is ready to run. See if it can run on 524 # target. 525 if not target.IsInGroup(descriptor.GetTargetGroup()): 526 # This test can't be run on this target, but it can be 527 # run on another target. 528 self.__AddToTargetPatternQueue(descriptor) 529 continue 530 531 self.__statuses[descriptor.GetId()].NoteReady() 532 return descriptor
533 534
535 - def __AddTestToStack(self, test_id):
536 """Adds 'test_id' to the stack of current tests. 537 538 returns -- True if the test was added to the stack; false if the 539 test could not be loaded. In the latter case, an 'UNTESTED' 540 result is recorded for the test.""" 541 542 self._Trace("Trying to add %s to stack" % test_id) 543 544 # Update test status. 545 self.__statuses[test_id].NoteQueued() 546 547 # Load the descriptor. 548 descriptor = self.__GetTestDescriptor(test_id) 549 if not descriptor: 550 return 0 551 552 # Check that all the prerequisites listed are actually present 553 # in the database. We may not actually run all of them, but if 554 # they're completely missing, that indicates a problem with 555 # either the descriptor or the database. 556 for p in descriptor.GetPrerequisites(): 557 if not self.__database.HasTest(p): 558 self.__AddUntestedResult( 559 test_id, 560 qm.message("prerequisite not in database", 561 prerequisite = p) 562 ) 563 return 0 564 565 # Ignore prerequisites that are not going to be run at all. 566 prereqs_iter = iter(descriptor.GetPrerequisites()) 567 relevant_prereqs = filter(self.__statuses.has_key, prereqs_iter) 568 569 # Store the test on the stack. 570 self.__ids_on_stack[test_id] = None 571 self.__test_stack.append((descriptor, relevant_prereqs)) 572 573 return 1
574 575
576 - def __AddToTargetPatternQueue(self, descriptor):
577 """A a test to the appropriate target pattern queue. 578 579 'descriptor' -- A 'TestDescriptor'. 580 581 Adds the test to the target pattern queue indicated in the 582 descriptor.""" 583 584 test_id = descriptor.GetId() 585 self.__statuses[test_id].NoteReady() 586 587 pattern = descriptor.GetTargetGroup() 588 589 # If we have not already determined whether or not this pattern 590 # matches any of the targets, do so now. 591 if not self.__pattern_ok.has_key(pattern): 592 self.__pattern_ok[pattern] = 0 593 for group in self.__target_groups: 594 if re.match(pattern, group): 595 self.__pattern_ok[pattern] = 1 596 patterns = self.__patterns.setdefault(group, []) 597 patterns.append(pattern) 598 # If none of the targets can run this test, mark it untested. 599 if not self.__pattern_ok[pattern]: 600 self.__AddUntestedResult(test_id, 601 "No target matching %s." % pattern) 602 return 603 604 queue = self.__target_pattern_queues.setdefault(pattern, []) 605 queue.append(descriptor)
606 607
608 - def __GetPendingPrerequisites(self, descriptor):
609 """Return pending prerequisite tests for 'descriptor'. 610 611 'descriptor' -- A 'TestDescriptor'. 612 613 returns -- A list of prerequisite test ids that have to 614 complete, or 'None' if one of the prerequisites had an 615 unexpected outcome.""" 616 617 needed = [] 618 619 prereqs = descriptor.GetPrerequisites() 620 for prereq_id, outcome in prereqs.iteritems(): 621 try: 622 prereq_status = self.__statuses[prereq_id] 623 except KeyError: 624 # This prerequisite is not being run at all, so skip 625 # it. 626 continue 627 628 if prereq_status.IsFinished(): 629 prereq_outcome = prereq_status.outcome 630 if outcome != prereq_outcome: 631 # Failed prerequisite. 632 self.__AddUntestedResult \ 633 (descriptor.GetId(), 634 qm.message("failed prerequisite"), 635 {'qmtest.prequisite': prereq_id, 636 'qmtest.outcome': prereq_outcome, 637 'qmtest.expected_outcome': outcome }) 638 return None 639 else: 640 # This prerequisite has not yet completed. 641 needed.append(prereq_id) 642 643 return needed
644 645
646 - def __AddResult(self, result):
647 """Report the result of running a test or resource. 648 649 'result' -- A 'Result' object representing the result of running 650 a test or resource.""" 651 652 # Output a trace message. 653 id = result.GetId() 654 self._Trace("Recording %s result for %s." % (result.GetKind(), id)) 655 656 # Find the target with the name indicated in the result. 657 if result.has_key(Result.TARGET): 658 for target in self.__targets: 659 if target.GetName() == result[Result.TARGET]: 660 break 661 else: 662 assert 0, ("No target %s exists (test id: %s)" 663 % (result[Result.TARGET], id)) 664 else: 665 # Not all results will have associated targets. If the 666 # test was not run at all, there will be no associated 667 # target. 668 target = None 669 670 # Having no target is a rare occurrence; output a trace message. 671 if not target: 672 self._Trace("No target for %s." % id) 673 674 # This target might now be idle. 675 if (target and target.IsIdle()): 676 # Output a trace message. 677 self._Trace("Target is now idle.\n") 678 self.__target_state[target] = self.__TARGET_IDLE 679 self.__has_idle_targets = 1 680 681 # Only tests have expectations or scheduling dependencies. 682 if result.GetKind() == Result.TEST: 683 # Record the outcome for this test. 684 test_status = self.__statuses[id] 685 test_status.outcome = result.GetOutcome() 686 687 # If there were tests waiting for this one to complete, they 688 # may now be ready to execute. 689 if test_status.dependants: 690 for dependant in test_status.dependants: 691 if not self.__statuses[dependant].HasBeenReady(): 692 descriptor = self.__GetTestDescriptor(dependant) 693 if not descriptor: 694 continue 695 prereqs = self.__GetPendingPrerequisites(descriptor) 696 if prereqs is None: 697 continue 698 if not prereqs: 699 # All prerequisites ran and were satisfied. 700 # This test can now run. 701 self.__AddToTargetPatternQueue(descriptor) 702 # Free the memory consumed by the list. 703 del test_status.dependants 704 705 # Check for unexpected outcomes. 706 if result.GetKind() == Result.TEST: 707 if (self.__expectations.Lookup(id).GetOutcome() 708 != result.GetOutcome()): 709 self.__any_unexpected_outcomes = 1 710 711 # Any targets that were starving may now be able to find 712 # work. 713 for t in self.__targets: 714 if self.__target_state[t] == self.__TARGET_STARVING: 715 self.__target_state[t] = self.__TARGET_IDLE 716 717 # Output a trace message. 718 self._Trace("Writing result for %s to streams." % id) 719 720 # Report the result. 721 for rs in self.__result_streams: 722 rs.WriteResult(result)
723 724
725 - def __CheckForResponse(self, wait):
726 """See if any of the targets have completed a task. 727 728 'wait' -- If false, this function returns immediately if there 729 is no available response. If 'wait' is true, this function 730 continues to wait until a response is available. 731 732 returns -- True iff a response was received.""" 733 734 while 1: 735 try: 736 # Read a reply from the response_queue. 737 result = self.__response_queue.get(0) 738 # Output a trace message. 739 self._Trace("Got %s result for %s from queue." 740 % (result.GetKind(), result.GetId())) 741 # Record the result. 742 self.__AddResult(result) 743 if result.GetKind() == Result.TEST: 744 assert self.__running > 0 745 self.__running -= 1 746 # Output a trace message. 747 self._Trace("Recorded result.") 748 return result 749 except qm.queue.Empty: 750 # If there is nothing in the queue, then this exception will 751 # be thrown. 752 if not wait: 753 return None 754 755 # Give other threads and processes a chance to run. 756 if self.__input_handlers: 757 # See if there is any input that might indicate that 758 # work has been done. 759 fds = self.__input_handlers.keys() 760 fds = select.select (fds, [], [], 0.1)[0] 761 for fd in fds: 762 self.__input_handlers[fd](fd) 763 else: 764 time.sleep(0.1) 765 766 # There may be a response now. 767 continue
768 769
770 - def __AddUntestedResult(self, test_name, cause, annotations={}, 771 exc_info = None):
772 """Add a 'Result' indicating that 'test_name' was not run. 773 774 'test_name' -- The label for the test that could not be run. 775 776 'cause' -- A string explaining why the test could not be run. 777 778 'annotations' -- A map from strings to strings giving 779 additional annotations for the result. 780 781 'exc_info' -- If this test could not be tested due to a thrown 782 exception, 'exc_info' is the result of 'sys.exc_info()' when the 783 exception was caught. 'None' otherwise.""" 784 785 # Remember that this test was started. 786 self.__num_tests_started += 1 787 788 # Create and record the result. 789 result = Result(Result.TEST, test_name, annotations = annotations) 790 if exc_info: 791 result.NoteException(exc_info, cause, Result.UNTESTED) 792 else: 793 result.SetOutcome(Result.UNTESTED, cause) 794 self.__AddResult(result)
795 796 797 ### Utility methods. 798
799 - def __GetTestDescriptor(self, test_id):
800 """Return the 'TestDescriptor' for 'test_id'. 801 802 returns -- The 'TestDescriptor' for 'test_id', or 'None' if the 803 descriptor could not be loaded. 804 805 If the database cannot load the descriptor, an 'UNTESTED' result 806 is recorded for 'test_id'.""" 807 808 try: 809 return self.__database.GetTest(test_id) 810 except: 811 self.__AddUntestedResult(test_id, 812 "Could not load test.", 813 exc_info = sys.exc_info()) 814 return None
815 816
817 - def _Trace(self, message):
818 """Write a trace 'message'. 819 820 'message' -- A string to be output as a trace message.""" 821 822 if __debug__: 823 tracer = qm.test.cmdline.get_qmtest().GetTracer() 824 tracer.Write(message, "exec")
825 826
827 - def _WriteInitialAnnotations(self):
828 829 # Calculate annotations. 830 start_time_str = qm.common.format_time_iso() 831 832 try: 833 username = qm.common.get_username() 834 except: 835 username = None 836 837 try: 838 uname = " ".join(os.uname()) 839 except: 840 uname = None 841 try: 842 userid = str(qm.common.get_userid()) 843 except: 844 userid = None 845 846 args_str = " ".join(sys.argv) 847 848 # Write them. 849 for rs in self.__result_streams: 850 rs.WriteAllAnnotations(self.__context) 851 rs.WriteAnnotation("qmtest.run.start_time", start_time_str) 852 if username is not None: 853 rs.WriteAnnotation("qmtest.run.username", username) 854 if userid is not None: 855 rs.WriteAnnotation("qmtest.run.userid", userid) 856 rs.WriteAnnotation("qmtest.run.version", qm.version) 857 if uname is not None: 858 rs.WriteAnnotation("qmtest.run.uname", uname) 859 rs.WriteAnnotation("qmtest.run.command_line", args_str)
860 861 862 ######################################################################## 863 # Local Variables: 864 # mode: python 865 # indent-tabs-mode: nil 866 # fill-column: 72 867 # End: 868

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.db-module.html0000664000076400007640000001640411122067145023152 0ustar stefanstefan qm.db
Package qm :: Module db
[hide private]
[frames] | no frames]

Module db

source code

Classes [hide private]
  Connection
A wrapper around a DB 2.0 connection.
Functions [hide private]
 
quote_string(string)
Quotes a string for SQL.
source code
Function Details [hide private]

quote_string(string)

source code 

Quotes a string for SQL.

'string' -- A string whose contents are to be used in an SQL literal string.

returns -- A SQL literal string whose contents match that of 'string'.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.suite-module.html0000664000076400007640000001100211122067145024661 0ustar stefanstefan qm.test.suite
Package qm :: Package test :: Module suite
[hide private]
[frames] | no frames]

Module suite

source code

Classes [hide private]
  Suite
A collection of tests.
qmtest-2.4.1/share/doc/qmtest/html/manual/mimetools.Message-class.html0000664000076400007640000003057311122067145025367 0ustar stefanstefan mimetools.Message
mimetools :: Message :: Class Message
[hide private]
[frames] | no frames]

Class Message

rfc822.Message --+
                 |
                Message

A derived class of rfc822.Message that knows about MIME headers and contains some hooks for decoding encoded and multipart messages.

Instance Methods [hide private]
 
__init__(self, fp, seekable=1)
Initialize the class instance and read the headers.
 
getencoding(self)
 
getmaintype(self)
 
getparam(self, name)
 
getparamnames(self)
 
getplist(self)
 
getsubtype(self)
 
gettype(self)
 
parseplist(self)
 
parsetype(self)

Inherited from rfc822.Message: __contains__, __delitem__, __getitem__, __iter__, __len__, __setitem__, __str__, get, getaddr, getaddrlist, getallmatchingheaders, getdate, getdate_tz, getfirstmatchingheader, getheader, getheaders, getrawheader, has_key, iscomment, isheader, islast, items, keys, readheaders, rewindbody, setdefault, values

Method Details [hide private]

__init__(self, fp, seekable=1)
(Constructor)

 

Initialize the class instance and read the headers.

Overrides: rfc822.Message.__init__
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.local_host-pysrc.html0000664000076400007640000007712011122067153027202 0ustar stefanstefan qm.test.classes.local_host
Package qm :: Package test :: Package classes :: Module local_host
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.local_host

 1  ######################################################################## 
 2  # 
 3  # File:   local_host.py 
 4  # Author: Mark Mitchell 
 5  # Date:   2005-06-03 
 6  # 
 7  # Contents: 
 8  #   LocalHost 
 9  # 
10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ####################################################################### 
17   
18  import os 
19  import os.path 
20  from   qm.host import Host 
21  import shutil 
22   
23  ######################################################################## 
24  # Classes 
25  ####################################################################### 
26   
27 -class LocalHost(Host):
28 """A 'LocalHost' is the machine on which Python is running. 29 30 The default directory for a 'LocalHost' is the current working 31 directory for this Python process.""" 32
33 - def UploadFile(self, local_file, remote_file = None):
34 35 if remote_file is None: 36 remote_file = os.path.basename(local_file) 37 # Do not copy the files if they are the same. 38 if not self._SameFile(local_file, remote_file): 39 shutil.copy(local_file, remote_file)
40 41
42 - def UploadAndRun(self, path, arguments, environment = None, 43 timeout = -1):
44 45 # There is no need to actually upload the file, since it is 46 # running on the local machine. 47 return self.Run(path, arguments, environment, timeout)
48 49
50 - def DownloadFile(self, remote_file, local_file = None):
51 52 return self.UploadFile(remote_file, local_file)
53 54
55 - def _SameFile(self, file1, file2):
56 """Return true iff 'file1' and 'file2' are the same file. 57 58 returns -- True iff 'file1' and 'file2' are the same file, 59 even if they have different names.""" 60 61 if not os.path.exists(file1) or not os.path.exists(file2): 62 return False 63 if hasattr(os.path, "samefile"): 64 return os.path.samefile(file1, file2) 65 return (os.path.normcase(os.path.abspath(file1)) 66 == os.path.normcase(os.path.abspath(file2)))
67 68
69 - def DeleteFile(self, remote_file):
70 71 os.remove(remote_file)
72

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.trace-module.html0000664000076400007640000000206411122067144024442 0ustar stefanstefan trace

Module trace


Classes

Tracer

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.executable-module.html0000664000076400007640000000260211122067144025463 0ustar stefanstefan executable

Module executable


Classes

Executable
Filter
RedirectedExecutable
TimeoutExecutable

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.resource.Resource-class.html0000664000076400007640000004410511122067150026773 0ustar stefanstefan qm.test.resource.Resource
Package qm :: Package test :: Module resource :: Class Resource
[hide private]
[frames] | no frames]

Class Resource

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
      runnable.Runnable --+
                          |
                         Resource
Known Subclasses:

A 'Resource' sets up before a test and cleans up afterwards.

Some tests take a lot of work to set up. For example, a database test that checks the result of SQL queries may require that the database first be populated with a substantial number of records. If there are many tests that all use the same set of records, it would be wasteful to set up the database for each test. It would be more efficient to set up the database once, run all of the tests, and then remove the databases upon completion.

You can use a 'Resource' to gain this efficiency. If a test depends on a resource, QMTest will ensure that the resource is available before the test runs. Once all tests that depend on the resource have been run QMTest will destroy the resource.

Each resource class (i.e., class derived from 'Resource') describes a set of "arguments". Each argument has a name and a type. The values of these arguments determine the design-time parameters for the resource. See the documentation for the 'Test' class for more complete information.

Each resource class also defines a 'SetUp' method that indicates how to set up the resource, and a 'CleanUp' method that indicates how to clean up afterwards.

'Resource' is an abstract class.

You can extend QMTest by providing your own resource class implementation. If the resource classes that come with QMTest cannot be used conveniently with your application domain, you may wish to create a new resource class.

To create your own resource class, you must create a Python class derived (directly or indirectly) from 'Resource'. The documentation for each method of 'Resource' indicates whether you must override it in your resource class implementation. Some methods may be overridden, but do not need to be. You might want to override such a method to provide a more efficient implementation, but QMTest will work fine if you just use the default version.

If QMTest calls a method on a resource and that method raises an exception that is not caught within the method itself, QMTest will catch the exception and continue processing.

Nested Classes [hide private]

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
SetUp(self, context, result)
Set up the resource.
source code
 
CleanUp(self, result)
Clean up the resource.
source code

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  kind = 'resource'
A string giving kind of extension is implemented by the class.

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, arguments, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

SetUp(self, context, result)

source code 

Set up the resource.

'context' -- A 'Context' giving run-time parameters to the resource. The resource may place additional variables into the 'context'; these variables will be visible to tests that depend on the resource.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

CleanUp(self, result)

source code 

Clean up the resource.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes may override this method.


././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command.build_extensions.build_extensions-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command.build_extensions.build_extensions-class.ht0000664000076400007640000003354611122067145033374 0ustar stefanstefan qm.dist.command.build_extensions.build_extensions
Package qm :: Package dist :: Package command :: Module build_extensions :: Class build_extensions
[hide private]
[frames] | no frames]

Class build_extensions

source code

          distutils.cmd.Command --+    
                                  |    
distutils.command.build_py.build_py --+
                                      |
                                     build_extensions

build extension files.

Instance Methods [hide private]
 
finalize_options(self)
Set final values for all the options that this command supports.
source code
 
get_input(self)
Return all files containing extension classes.
source code
 
run(self)
A command's raison d'etre: carry out the action it exists to perform, controlled by the options initialized in 'initialize_options()', customized by other commands, the setup script, the command-line, and config files, and finalized in 'finalize_options()'.
source code

Inherited from distutils.command.build_py.build_py: build_module, build_modules, build_package_data, build_packages, byte_compile, check_module, check_package, find_all_modules, find_data_files, find_modules, find_package_modules, get_data_files, get_module_outfile, get_outputs, get_package_dir, get_source_files, initialize_options

Inherited from distutils.cmd.Command: __getattr__, __init__, announce, copy_file, copy_tree, debug_print, dump_options, ensure_dirname, ensure_filename, ensure_finalized, ensure_string, ensure_string_list, execute, get_command_name, get_finalized_command, get_sub_commands, make_archive, make_file, mkpath, move_file, reinitialize_command, run_command, set_undefined_options, spawn, warn

Inherited from distutils.cmd.Command (private): _ensure_stringlike, _ensure_tested_string

Class Variables [hide private]
  description = 'build qmtest extension classes.'

Inherited from distutils.command.build_py.build_py: boolean_options, negative_opt, user_options

Inherited from distutils.cmd.Command: sub_commands

Method Details [hide private]

finalize_options(self)

source code 

Set final values for all the options that this command supports. This is always called as late as possible, ie. after any option assignments from the command-line or from other commands have been done. Thus, this is the place to code option dependencies: if 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as long as 'foo' still has the same value it was assigned in 'initialize_options()'.

This method must be implemented by all command classes.

Overrides: distutils.cmd.Command.finalize_options
(inherited documentation)

run(self)

source code 

A command's raison d'etre: carry out the action it exists to perform, controlled by the options initialized in 'initialize_options()', customized by other commands, the setup script, the command-line, and config files, and finalized in 'finalize_options()'. All terminal output and filesystem interaction should be done by 'run()'.

This method must be implemented by all command classes.

Overrides: distutils.cmd.Command.run
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler.Compiler-class.html0000664000076400007640000010214711122067147030404 0ustar stefanstefan qm.test.classes.compiler.Compiler
Package qm :: Package test :: Package classes :: Module compiler :: Class Compiler
[hide private]
[frames] | no frames]

Class Compiler

source code

A 'Compiler' compiles and links source files.

Instance Methods [hide private]
 
__init__(self, path, options=None, ldflags=None)
Construct a new 'Compiler'.
source code
 
Compile(self, mode, files, dir, options=[], ldflags=[], output=None, timeout=-1)
Compile the 'files'.
source code
 
ExecuteCommand(self, dir, command, timeout=-1)
Execute 'command' in 'dir'.
source code
 
GetCompilationCommand(self, mode, files, options=[], ldflags=[], output=None)
Return the appropriate command for compiling 'files'.
source code
 
ParseOutput(self, output, ignore_regexps=())
Turn the 'output' into a sqeuence of 'Diagnostic's.
source code
 
GetPath(self)
Return the location of the executable.
source code
 
GetOptions(self)
Return the list of compilation options.
source code
 
SetOptions(self, options)
Reset the list of compiler options.
source code
 
GetLDFlags(self)
Return the list of link options.
source code
 
SetLDFlags(self, ldflags)
Reset the list of link options.
source code
 
GetExecutableExtension(self)
Return the extension for executables.
source code
 
GetObjectExtension(self)
Return the extension for object files.
source code
 
_GetModeSwitches(self, mode)
Return the compilation switches for the compilation 'mode'.
source code
Class Variables [hide private]
  MODE_PREPROCESS = 'preprocess'
Preprocess the source files, but do not compile them.
  MODE_COMPILE = 'compile'
Compile the source files, but do not assemble them.
  MODE_ASSEMBLE = 'assemble'
Compile the source files, but do not link them.
  MODE_LINK = 'link'
Compile and link the source files.
  modes = [MODE_COMPILE, MODE_ASSEMBLE, MODE_LINK, MODE_PREPROCESS]
The available compilation modes.
Method Details [hide private]

__init__(self, path, options=None, ldflags=None)
(Constructor)

source code 

Construct a new 'Compiler'.

'path' -- A string giving the location of the compiler executable.

'options' -- A list of strings indicating options to the compiler, or 'None' if there are no options.

'ldflags' -- A list of strings indicating ld flags to the compiler, or 'None' if there are no flags.

Compile(self, mode, files, dir, options=[], ldflags=[], output=None, timeout=-1)

source code 

Compile the 'files'.

'mode' -- The compilation mode (one of the 'Compiler.modes') that should be used to compile the 'files'.

'files' -- A sequence of strings giving the names of source files (including, in general, assembly files, object files, and libraries) that should be compiled.

'dir' -- The directory in which to run the compiler.

'options' -- A sequence of strings indicating additional options that should be provided to the compiler.

'ldflags' -- A sequence of strings indicating additional linker flags that should be provided to the compiler, if linking is done.

'output' -- The name of the file should be created by the compilation. If 'None', the compiler will use a default value.

'timeout' -- The maximum number of seconds the compiler is permitted to run. If 'timeout' is -1, the compiler is permitted to run forever.

returns -- A tuple '(status, output)'. The 'status' is the exit status returned by the compiler, as indicated by 'waitpid'. The 'output' is a string containing the standard outpt and standard errror generated by the compiler.

ExecuteCommand(self, dir, command, timeout=-1)

source code 

Execute 'command' in 'dir'.

'dir' -- The directory in which to execute the command.

'command' -- A sequence of strings, as returned by 'GetCompilationCommand'.

'timeout' -- The maximum number of seconds the compiler is permitted to run. If 'timeout' is -1, the compiler is permitted to run forever.

returns -- A tuple '(status, output)'. The 'status' is the exit status returned by the compiler, as indicated by 'waitpid'. The 'output' is a string containing the standard output and standard errror generated by the compiler.

GetCompilationCommand(self, mode, files, options=[], ldflags=[], output=None)

source code 

Return the appropriate command for compiling 'files'.

'mode' -- The compilation mode (one of the 'Compiler.modes') that should be used to compile the 'files'.

'files' -- A sequence of strings giving the names of source files (including, in general, assembly files, object files, and libraries) that should be compiled.

'options' -- A sequence of strings indicating additional options that should be provided to the compiler.

'ldflags' -- A sequence of strings indicating additional linker flags that should be provided to the compiler, if linking is done.

'output' -- The name of the file should be created by the compilation. If 'None', the compiler will use a default value. (In some cases there may be multiple outputs. For example, when generating multiple object files from multiple source files, the compiler will create a variety of objects.)

returns -- A sequence of strings indicating the arguments, including 'argv[0]', for the compilation command.

ParseOutput(self, output, ignore_regexps=())

source code 

Turn the 'output' into a sqeuence of 'Diagnostic's.

'output' -- A string containing the compiler's output.

'ignore_regexps' -- A sequence of regular expressions. If a diagnostic message matches one of these regular expressions, it will be ignored.

returns -- A list of 'Diagnostic's corresponding to the messages indicated in 'output', in the order that they were emitted.

GetPath(self)

source code 

Return the location of the executable.

returns -- A string giving the location of the executable. This location is the one that was specified as the 'path' argument to '__init__'.

GetOptions(self)

source code 

Return the list of compilation options.

returns -- A list of strings giving the compilation options specified when the 'Compiler' was constructed.

SetOptions(self, options)

source code 

Reset the list of compiler options.

'options' -- A list of strings indicating options to the compiler, or 'None' if there are no options.

GetLDFlags(self)

source code 

Return the list of link options.

returns -- A list of strings giving the link options specified when the 'Compiler' was constructed.

SetLDFlags(self, ldflags)

source code 

Reset the list of link options.

'ldflags' -- A list of strings indicating options to the linker, or 'None' if there are no flags.

GetExecutableExtension(self)

source code 

Return the extension for executables.

returns -- The extension (including leading '.', if applicable) for executable files created by this compiler.

GetObjectExtension(self)

source code 

Return the extension for object files.

returns -- The extension (including leading '.', if applicable) for object files created by this compiler.

_GetModeSwitches(self, mode)

source code 

Return the compilation switches for the compilation 'mode'.

'mode' -- The compilation mode (one of 'Compiler.modes').

returns -- A sequence of strings indicating the switches that are used to indicate the compilation mode.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.sql_result_stream._Buffer-class.html0000664000076400007640000002213411122067147032135 0ustar stefanstefan qm.test.classes.sql_result_stream._Buffer
Package qm :: Package test :: Package classes :: Module sql_result_stream :: Class _Buffer
[hide private]
[frames] | no frames]

Class _Buffer

source code

A little buffering iterator with one-element rewind.

Instance Methods [hide private]
 
__init__(self, size, get_more)
Create a '_Buffer'.
source code
 
next(self)
Returns the next item, refilling the buffer if necessary.
source code
 
rewind(self) source code
 
__iter__(self) source code
Method Details [hide private]

__init__(self, size, get_more)
(Constructor)

source code 
Create a '_Buffer'.

'size' -- the number of items to hold in the buffer at a time.

'get_more' -- a function taking a number as its sole argument;
              should return a list of that many new items (or as
              many items are left, whichever is less).


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.structured_text.TextFormatter-class.html0000664000076400007640000005645711122067146030501 0ustar stefanstefan qm.structured_text.TextFormatter
Package qm :: Module structured_text :: Class TextFormatter
[hide private]
[frames] | no frames]

Class TextFormatter

source code

Formatter --+
            |
           TextFormatter

Formatter for generating plain text from structured text.

Instance Methods [hide private]
 
__init__(self, output_file=sys.stdout, width=78, indent_size=2, indent=0, list_bullet='-')
Create a new HTML formatter.
source code
 
End(self)
End the processed text document.
source code
 
WriteText(self, text)
Write ordinary text.
source code
 
StartList(self, type)
Start a list environment of type 'type'.
source code
 
EndList(self, type)
End a list environment of type 'type'.
source code
 
StartItem(self, type, label=None)
Begin an element to the environment of type 'type'.
source code
 
FinishDefinedTerm(self)
Finish the definition of a term in a definition list.
source code
 
EndItem(self, type)
End an element in the environment of type 'type'.
source code
 
StartStyle(self, style)
Start a new text style 'style'.
source code
 
EndStyle(self, style)
End the text style 'style'.
source code
 
StartLink(self, target)
Being a hyperlink to 'target'.
source code
 
EndLink(self)
End a hyperlink.
source code
 
__IndentTo(self, col) source code
 
__Write(self, text) source code
 
__NextLine(self) source code
Class Variables [hide private]
  __style_markers = {'emphasized': '*', 'literal': '\'', 'strong...
Method Details [hide private]

__init__(self, output_file=sys.stdout, width=78, indent_size=2, indent=0, list_bullet='-')
(Constructor)

source code 

Create a new HTML formatter.

'output_file' -- A file object to which HTML source is written.

StartItem(self, type, label=None)

source code 

Begin an element to the environment of type 'type'.

'label' -- If type is "ordered list", this is the label for this list element.


Class Variable Details [hide private]

__style_markers

Value:
{'emphasized': '*',
 'literal': '\'',
 'strong': '**',
 'underlined': '_',
 'verbatim': '\'\'\''}

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.structured_text.Formatter-class.html0000664000076400007640000001026211122067146027614 0ustar stefanstefan qm.structured_text.Formatter
Package qm :: Module structured_text :: Class Formatter
[hide private]
[frames] | no frames]

Class Formatter

source code

Known Subclasses:

Interface for output formatters for the 'StructuredTextProcessor'.

Valid list environment types are

  * definition list

  * ordered list

  * paragraph

  * unordered list

Valid styles are

  * emphasized

  * strong

  * underlined

  * literal

  * verbatim

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate-module.html0000664000076400007640000002576011122067145027665 0ustar stefanstefan qm.external.DocumentTemplate
Package qm :: Package external :: Package DocumentTemplate
[hide private]
[frames] | no frames]

Package DocumentTemplate

source code

Package wrapper for Document Template

This wrapper allows the (now many) document template modules to be segregated in a separate package.

$Id: __init__.py 40218 2005-11-18 14:39:19Z andreasjung $


Version: 1.18

Submodules [hide private]

Variables [hide private]
  __doc__ = '''Package wrapper for Document Templ...
Variables Details [hide private]

__doc__

Value:
'''Package wrapper for Document Template

This wrapper allows the (now many) document template modules to be
segregated in a separate package.

$Id: __init__.py 40218 2005-11-18 14:39:19Z andreasjung $'''

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.resource_adapter-pysrc.html0000664000076400007640000003621311122067160026742 0ustar stefanstefan qm.test.resource_adapter
Package qm :: Package test :: Module resource_adapter
[hide private]
[frames] | no frames]

Source Code for Module qm.test.resource_adapter

 1  ######################################################################## 
 2  # 
 3  # File:   resource_adapter.py 
 4  # Author: Mark Mitchell 
 5  # Date:   2005-09-02 
 6  # 
 7  # Contents: 
 8  #   QMTest ResourceAdapter class. 
 9  # 
10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from qm.test.resource import Resource 
21   
22  ######################################################################## 
23  # Classes 
24  ######################################################################## 
25   
26 -class ResourceAdapter(Resource):
27 """A 'ResourceAdapter' converts test classes to resource classes. 28 29 If 'C' is a test class, then a class derived from 30 'ResourceAdapter' and 'C' (in that order!) will be a resource 31 class. The resource class 'Setup' method is equivalent to the 32 'Test' class 'Run' method. The 'CleanUp' action is empty.""" 33
34 - def SetUp(self, context, result):
35 36 # To set up the resource, just run the underlying test class. 37 self.Run(context, result)
38

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.gparse-module.html0000664000076400007640000002411111122067145031132 0ustar stefanstefan qm.external.DocumentTemplate.gparse
Package qm :: Package external :: Package DocumentTemplate :: Module gparse
[hide private]
[frames] | no frames]

Module gparse

source code

$Id: gparse.py 1069 2008-11-13 21:55:43Z stefan $

Functions [hide private]
 
munge(ast, STAR=16, DOT=23, LSQB=9, COLON=11, trailer=321) source code
 
slice_munge(ast, i) source code
 
item_munge(ast, i) source code
 
dot_munge(ast, i) source code
 
multi_munge(ast) source code
 
compile(src, file_name, ctype) source code
Variables [hide private]
  ParseError = 'Expression Parse Error'
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.TupleField-class.html0000664000076400007640000006360211122067146025712 0ustar stefanstefan qm.fields.TupleField
qm :: fields :: TupleField :: Class TupleField
[hide private]
[frames] | no frames]

Class TupleField

source code

object --+    
         |    
     Field --+
             |
            TupleField

A 'TupleField' contains zero or more other 'Field' objects.

The contained 'Field' objects may have different types. The value of a 'TupleField' is a Python list; the values in the list correspond to the values of the contained 'Field' objects. For example, '["abc", 3]' would be a valid value for a 'TupleField' containing a 'TextField' and an 'IntegerField'.

Instance Methods [hide private]
 
__init__(self, name='', fields=None, **properties)
Construct a new 'TupleField'.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
GetSubfields(self)
Returns the sequence of subfields contained in this field.
source code
 
FormatValueAsHtml(self, server, value, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
MakeDomNodeForValue(self, value, document)
Generate a DOM element node for a value of this field.
source code
 
Validate(self, value)
Validate a field value.
source code
 
ParseFormValue(self, request, name, attachment_stores)
Convert a value submitted from an HTML form.
source code
 
GetValueFromDomNode(self, node, attachment_store)
Return a value for this field represented by DOM 'node'.
source code

Inherited from Field: FormatValueAsText, GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetTitle, IsComputed, IsHidden, IsReadOnly, ParseTextValue, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', fields=None, **properties)
(Constructor)

source code 

Construct a new 'TupleField'.

'name' -- The name of the field.

'fields' -- A sequence of 'Field' instances.

The new 'TupleField' stores a list whose elements correspond to the 'fields'.

Overrides: object.__init__

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: Field.GetHelp
(inherited documentation)

GetSubfields(self)

source code 

Returns the sequence of subfields contained in this field.

returns -- The sequence of subfields contained in this field. If there are no subfields, an empty sequence is returned.

Overrides: Field.GetSubfields
(inherited documentation)

FormatValueAsHtml(self, server, value, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

Overrides: Field.FormatValueAsHtml
(inherited documentation)

MakeDomNodeForValue(self, value, document)

source code 

Generate a DOM element node for a value of this field.

'value' -- The value to represent.

'document' -- The containing DOM document node.

Overrides: Field.MakeDomNodeForValue
(inherited documentation)

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

Overrides: Field.Validate
(inherited documentation)

ParseFormValue(self, request, name, attachment_stores)

source code 

Convert a value submitted from an HTML form.

'request' -- The 'WebRequest' containing a value corresponding to this field.

'name' -- The name corresponding to this field in the 'request'.

'attachment_stores' -- A dictionary mapping 'AttachmentStore' ids (in the sense of Python's 'id' built-in) to the 'AttachmentStore's themselves.

returns -- A pair '(value, redisplay)'. 'value' is the value for this field, as indicated in 'request'. 'redisplay' is true if and only if the form should be redisplayed, rather than committed. If an error occurs, an exception is thrown.

Overrides: Field.ParseFormValue
(inherited documentation)

GetValueFromDomNode(self, node, attachment_store)

source code 

Return a value for this field represented by DOM 'node'.

This method does not validate the value for this particular instance; it only makes sure the node is well-formed, and returns a value of the correct Python type.

'node' -- The DOM node that is being evaluated.

'attachment_store' -- For attachments, the store that should be used.

If the 'node' is incorrectly formed, this method should raise an exception.

Overrides: Field.GetValueFromDomNode
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.common.RcConfiguration-class.html0000664000076400007640000003574211122067145026776 0ustar stefanstefan qm.common.RcConfiguration
Package qm :: Module common :: Class RcConfiguration
[hide private]
[frames] | no frames]

Class RcConfiguration

source code

ConfigParser.RawConfigParser --+    
                               |    
       ConfigParser.ConfigParser --+
                                   |
                                  RcConfiguration

Interface object to QM configuration files.

Configuration files are in the format parsed by the standard 'ConfigParser' module, namely 'win.ini'--style files.

Instance Methods [hide private]
 
__init__(self)
Create a new configuration instance.
source code
 
Load(self, section)
Load configuration.
source code
 
Get(self, option, default, section=None)
Retrieve a configuration variable.
source code
 
GetOptions(self, section=None)
Return a sequence of options.
source code

Inherited from ConfigParser.ConfigParser: get, items

Inherited from ConfigParser.ConfigParser (private): _interpolate, _interpolation_replace

Inherited from ConfigParser.RawConfigParser: add_section, defaults, getboolean, getfloat, getint, has_option, has_section, options, optionxform, read, readfp, remove_option, remove_section, sections, set, write

Inherited from ConfigParser.RawConfigParser (private): _get, _read

Class Variables [hide private]
  user_rc_file_name = '.qmrc'
The name of the user configuration file.

Inherited from ConfigParser.ConfigParser (private): _KEYCRE

Inherited from ConfigParser.RawConfigParser: OPTCRE, SECTCRE

Inherited from ConfigParser.RawConfigParser (private): _boolean_states

Method Details [hide private]

__init__(self)
(Constructor)

source code 

Create a new configuration instance.

Overrides: ConfigParser.RawConfigParser.__init__

Load(self, section)

source code 

Load configuration.

'section' -- The configuration section from which subsequent variables are loaded.

Get(self, option, default, section=None)

source code 

Retrieve a configuration variable.

'option' -- The name of the option to retrieve.

'default' -- The default value to return if the option is not found.

'section' -- The section from which to retrieve the option. 'None' indicates the section specified to the 'Load' method for this instance.

precondition -- The RC configuration must be loaded.

GetOptions(self, section=None)

source code 

Return a sequence of options.

'section' -- The section for which to list options, or 'None' for the section specified to 'Load'.

precondition -- The RC configuration must be loaded.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_thread.ExecutionThread-class.html0000664000076400007640000004063411122067150032005 0ustar stefanstefan qm.test.execution_thread.ExecutionThread
Package qm :: Package test :: Module execution_thread :: Class ExecutionThread
[hide private]
[frames] | no frames]

Class ExecutionThread

source code

                  object --+        
                           |        
          threading._Verbose --+    
                               |    
                threading.Thread --+
                                   |
execution_engine.ExecutionEngine --+
                                   |
                                  ExecutionThread

A 'ExecutionThread' executes tests in a separate thread.

A 'ExecutionThread' is an 'ExecutionEngine' that runs tests in a separate thread.

This class schedules the tests, plus the setup and cleanup of any resources they require, across one or more targets.

The shedule is determined dynamically as the tests are executed based on which targets are idle and which are not. Therefore, the testing load should be reasonably well balanced, even across a heterogeneous network of testing machines.

Instance Methods [hide private]
 
__init__(self, database, test_ids, context, targets, result_streams=None, expectations=None)
Set up a test run.
source code
 
run(self)
Run the tests.
source code
 
RequestTermination(self)
Request termination.
source code
 
_IsTerminationRequested(self)
Returns true if termination has been requested.
source code

Inherited from threading.Thread: __repr__, getName, isAlive, isDaemon, join, setDaemon, setName, start

Inherited from threading.Thread (private): _set_daemon

Inherited from threading._Verbose (private): _note

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Inherited from execution_engine.ExecutionEngine: AddInputHandler, Run

Inherited from execution_engine.ExecutionEngine (private): _RunTests, _Trace, _WriteInitialAnnotations

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, test_ids, context, targets, result_streams=None, expectations=None)
(Constructor)

source code 

Set up a test run.

'database' -- The 'Database' containing the tests that will be run.

'test_ids' -- A sequence of IDs of tests to run. Where possible, the tests are started in the order specified.

'context' -- The context object to use when running tests.

'targets' -- A sequence of 'Target' objects, representing targets on which tests may be run.

'result_streams' -- A sequence of 'ResultStream' objects. Each stream will be provided with results as they are available. This thread will not perform any locking of these streams as they are written to; each stream must provide its own synchronization if it will be accessed before 'run' returns.

'expectations' -- If not 'None', a dictionary mapping test IDs to expected outcomes.

Overrides: execution_engine.ExecutionEngine.__init__

run(self)

source code 

Run the tests.

This method runs the tests specified in the __init__ function.

Overrides: threading.Thread.run

RequestTermination(self)

source code 

Request termination.

Request that the execution thread be terminated. This may take some time; tests that are already running will continue to run, for example.

Overrides: execution_engine.ExecutionEngine.RequestTermination

_IsTerminationRequested(self)

source code 

Returns true if termination has been requested.

return -- True if Terminate has been called.

Overrides: execution_engine.ExecutionEngine._IsTerminationRequested

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.diagnostic-pysrc.html0000664000076400007640000016103711122067154024567 0ustar stefanstefan qm.diagnostic
Package qm :: Module diagnostic
[hide private]
[frames] | no frames]

Source Code for Module qm.diagnostic

  1  ######################################################################## 
  2  # 
  3  # File:   diagnostic.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-02-27 
  6  # 
  7  # Contents: 
  8  #   Code for managing and generating diagnostics. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  """Table-based diagnostic message generation. 
 17   
 18  Diagnostics are loaded from text files.  These files are laid out 
 19  according to special rules: 
 20   
 21    - Lines beginning with a hash mark are ignored. 
 22   
 23    - Each diagnostic begins with a line that contains an at sign (@) and 
 24      a tag used to identify the diagnostic. 
 25   
 26    - Subsequent text until the start of the next diagnostic is 
 27      the diagnostic template. 
 28   
 29    - Diagnostic templates may contain named-substition tokens as 
 30      used by the Python % operator on a string. 
 31   
 32    - Diagnostic messages are interpreted as structured text. 
 33   
 34  For example: 
 35   
 36      # This line is a comment 
 37   
 38      @ my first diagnostic 
 39      The command you entered, '$(command)s', is bogus.  Please try again. 
 40   
 41      @ my second diagnostic 
 42      The value you specified, '$(value)d', is completely bogus.  Don't 
 43      even bother trying again. 
 44   
 45  """ 
 46   
 47  ######################################################################## 
 48  # imports 
 49  ######################################################################## 
 50   
 51  import common 
 52  import os 
 53  import qm 
 54  import re 
 55  import string 
 56  import types 
 57   
 58  ######################################################################## 
 59  # classes 
 60  ######################################################################## 
 61   
62 -class DiagnosticSet:
63 64 # Regular expression to match comment lines. 65 __comment_regex = re.compile("^[ \t]*#.*$", re.MULTILINE) 66 67 # Regular express that matches the start of a new diagnostic entry. 68 __separator_regex = re.compile("^@", re.MULTILINE) 69 70
71 - def __init__(self):
72 """Initialize a new set of diagnostics.""" 73 74 self.__diagnostics = {}
75 76
77 - def ReadFromFile(self, path):
78 """Load diagnostics from a file. 79 80 'path' -- Path to the file containing diagnostics.""" 81 82 # Read the file. 83 file = open(path, "r") 84 contents = file.read() 85 file.close() 86 # Erase comment lines. 87 contents = self.__comment_regex.sub("", contents) 88 # Split the file's contents into entries. 89 entries = self.__separator_regex.split(contents) 90 91 for entry in entries: 92 if not "\n" in entry: 93 continue 94 # The tag is everything up to the first newline. 95 tag, message = string.split(entry, "\n", 1) 96 # Clean up the tag and the diagnostic message. 97 tag = string.strip(tag) 98 message = string.strip(message) 99 # Store it. 100 self.__diagnostics[tag] = message
101 102
103 - def Generate(self, tag, severity="error", output=None, **substitutions):
104 """Generate a diagnostic message. 105 106 'tag' -- The tag of the diagnostic to generate. 107 108 'severity' -- A string representing the severity of the 109 diagnostic, for instance "warning" or "error". 110 111 'output' -- If not 'None', the a file object to which the 112 a full diagnostic is written. 113 114 'substitutions' -- Named values for substitution into the 115 diagnostic message. 116 117 returns -- The bare diagnostic message.""" 118 119 substitutions = substitutions.copy() 120 substitutions["program_name"] = common.program_name 121 message = self.__diagnostics[tag] % substitutions 122 if output is None: 123 pass 124 else: 125 output.write("%s: %s: %s\n" 126 % (common.program_name, severity, message)) 127 return message
128 129 130 ######################################################################## 131 # Variables 132 ######################################################################## 133 134 __diagnostic_set = None 135 """The 'DiagnosticSet' object from which diagnostics are generated.""" 136 137 __help_set = None 138 """The 'DiagnosticSet'object from which help text messages are 139 generated.""" 140 141 ######################################################################## 142 # functions 143 ######################################################################## 144
146 """Return the 'DiagnosticSet' containing warning/error messages. 147 148 returns -- The 'DiagnosticSet' containing warning/error messages.""" 149 150 global __diagnostic_set 151 if __diagnostic_set is None: 152 __diagnostic_set = DiagnosticSet() 153 __diagnostic_set.ReadFromFile(qm.get_share_directory("diagnostics", 154 "common.txt")) 155 156 return __diagnostic_set
157 158
159 -def get_help_set():
160 """Return the 'DiagnosticSet' for help messages. 161 162 returns -- The 'DiagnosticSet' containing help messages.""" 163 164 global __help_set 165 if __help_set is None: 166 __help_set = DiagnosticSet() 167 __help_set.ReadFromFile(qm.get_share_directory("diagnostics", 168 "common-help.txt")) 169 170 return __help_set
171 172
173 -def message(tag, **substitutions):
174 """Generate a diagnostic message.""" 175 176 return apply(get_diagnostic_set().Generate, 177 (tag, "message", None), 178 substitutions)
179 180
181 -def error(tag, output=None, **substitutions):
182 """Generate or emit an error diagnostic.""" 183 184 return apply(get_diagnostic_set().Generate, 185 (tag, "error", output, ), 186 substitutions)
187 188
189 -def warning(tag, output=None, **substitutions):
190 """Generate or emit a warning diagnostic.""" 191 192 return apply(get_diagnostic_set().Generate, 193 (tag, "warning", output, ), 194 substitutions)
195 196
197 -def load_messages(tool):
198 """Read messages that apply to 'tool'. 199 200 'tool' -- A string giving the name of a QM tool.""" 201 202 # Load diagnostics. 203 diagnostic_file = qm.get_share_directory('messages', 'diagnostics.txt') 204 get_diagnostic_set().ReadFromFile(diagnostic_file) 205 # Load help messages. 206 diagnostic_file = qm.get_share_directory('messages', 'help.txt') 207 get_help_set().ReadFromFile(diagnostic_file)
208 209 ######################################################################## 210 # Local Variables: 211 # mode: python 212 # indent-tabs-mode: nil 213 # fill-column: 72 214 # End: 215

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.AddressInUseError-class.html0000664000076400007640000001535511122067151026525 0ustar stefanstefan qm.web.AddressInUseError
Package qm :: Module web :: Class AddressInUseError
[hide private]
[frames] | no frames]

Class AddressInUseError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  AddressInUseError

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.host-pysrc.html0000664000076400007640000024137011122067160023414 0ustar stefanstefan qm.host
Package qm :: Module host
[hide private]
[frames] | no frames]

Source Code for Module qm.host

  1  ######################################################################## 
  2  # 
  3  # File:   host.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2005-06-03 
  6  # 
  7  # Contents: 
  8  #   Host 
  9  # 
 10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ####################################################################### 
 17   
 18  from   qm.executable import RedirectedExecutable 
 19  from   qm.extension import Extension 
 20  import os.path 
 21   
 22  ######################################################################## 
 23  # Classes 
 24  ####################################################################### 
 25   
26 -class Host(Extension):
27 """A 'Host' is a logical machine. 28 29 Each logical machine has a default directory. When a file is 30 uploaded to or downloaded from the machine, and a relative path 31 is specified, the patch is relative to the default directory. 32 Similarly, when a program is run on the remote machine, its 33 initial working directory is the default directory. 34 35 The interface presented by 'Host' is a lowest common 36 denominator. The objective is not to expose all the functionality 37 of any host; rather it is to provide an interface that can be used 38 on many hosts.""" 39 40 kind = "host" 41
42 - class Executable(RedirectedExecutable):
43 """An 'Executable' is a simple redirected executable. 44 45 The standard error and standard output streams are combined 46 into a single stream. 47 48 The standard input is not closed before 49 invoking the program because SSH hangs if its standard input 50 is closed before it is invoked. For example, running: 51 52 ssh machine echo hi <&- 53 54 will hang with some versions of SSH.""" 55
56 - def _StderrPipe(self):
57 58 return None
59 60
61 - def __init__(self, arguments = None, **args):
62 63 if arguments: args.update(arguments) 64 super(Host, self).__init__(**args)
65 66
67 - def Run(self, path, arguments, environment = None, timeout = -1, 68 relative = False):
69 """Run a program on the remote host. 70 71 'path' -- The name of the program to run, on the remote host. 72 If 'relative' is true, or if 'path' is not an absolute path 73 but does contain at least one directory separator, then 'path' 74 is interpreted relative to the default directory. Otherwise, 75 'path' is used unmodified. 76 77 'arguments' -- The sequence of arguments that should be passed 78 to the program. 79 80 'environment' -- If not 'None', a dictionary of pairs of 81 strings to add to the environment of the running program. 82 83 'timeout' -- The number of seconds the program is permitted 84 to execute. After the 'timeout' expires, the program will be 85 terminated. However, in some cases (such as when using 'rsh') 86 it will be the local side of the connection that is closed. 87 The remote side of the connection may or may not continue to 88 operate, depending on the vagaries of the remote operating 89 system. 90 91 returns -- A pair '(status, output)'. The 'status' is the 92 exit status returned by the program, or 'None' if the exit 93 status is not available. The 'output' is a string giving the 94 combined standard output and standard error output from the 95 program.""" 96 97 # Compute the full environment for the child. 98 if environment is not None: 99 new_environment = os.environ.copy() 100 new_environment.update(environment) 101 environment = new_environment 102 executable = self.Executable(timeout) 103 if relative: 104 path = os.path.join(os.curdir, path) 105 status = executable.Run([path] + arguments, environment) 106 return (status, executable.stdout)
107 108
109 - def UploadFile(self, local_file, remote_file = None):
110 """Copy 'local_file' to 'remote_file'. 111 112 'local_file' -- The name of the file on the local machine. 113 114 'remote_file' -- The name of the file on the remote machine. 115 The 'remote_file' must be a relative path. It is interpreted 116 relative to the default directory. If 'None', the 117 'remote_file' is placed in the default directory using the 118 basename of the 'local_file'. 119 120 If the 'local_file' and 'remote_file' are the same, then this 121 function succeeds, but takes no action.""" 122 123 raise NotImplementedError
124 125
126 - def DownloadFile(self, remote_file, local_file):
127 """Copy 'remote_file' to 'local_file'. 128 129 'remote_file' -- The name of the file on the remote machine. 130 The 'remote_file' must be a relative path. It is interpreted 131 relative to the default directory. 132 133 'local_file' -- The name of the file on the local machine. If 134 'None', the 'local_file' is placed in the current directory 135 using the basename of the 'remote_file'. 136 137 If the 'local_file' and 'remote_file' are the same, then this 138 function succeeds, but takes no action.""" 139 140 raise NotImplementedError
141 142
143 - def UploadAndRun(self, path, arguments, environment = None, 144 timeout = -1):
145 """Run a program on the remote host. 146 147 'path' -- The name of the program to run, as a path on the 148 local machine. 149 150 'arguments' -- As for 'Run'. 151 152 'environment' -- As for 'Run'. 153 154 'timeout' -- As for 'Run'. 155 156 returns -- As for 'Run'. 157 158 The program is uploaded to the default directory on the remote 159 host, run, and then deleted.""" 160 161 self.UploadFile(path) 162 basename = os.path.basename(path) 163 result = self.Run(basename, 164 arguments, 165 environment, 166 timeout, 167 relative = True) 168 self.DeleteFile(basename) 169 return result
170 171
172 - def DeleteFile(self, remote_file):
173 """Delete the 'remote_file'. 174 175 'remote_file' -- A relative path to the file to be deleted.""" 176 177 raise NotImplementedError
178

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.sql_result_stream._SQLConnected-class.html0000664000076400007640000004764511122067147033224 0ustar stefanstefan qm.test.classes.sql_result_stream._SQLConnected
Package qm :: Package test :: Package classes :: Module sql_result_stream :: Class _SQLConnected
[hide private]
[frames] | no frames]

Class _SQLConnected

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     _SQLConnected
Known Subclasses:

Mixin class for classes that need a database connection.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.fields.TextField'> db_name>, <<class ...
A list of the arguments to the extension class.
  _argument_dictionary = {'connection': <<class 'qm.fields.Pytho...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.TextField'> db_module>, <...
A list of all the 'Field's in this class.
  connection = None
  db_module = 'pgdb'
  db_name = ''

Inherited from extension.Extension: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[<<class 'qm.fields.TextField'> db_name>,
 <<class 'qm.fields.TextField'> db_module>,
 <<class 'qm.fields.PythonField'> connection>]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'connection': <<class 'qm.fields.PythonField'> connection>,
 'db_module': <<class 'qm.fields.TextField'> db_module>,
 'db_name': <<class 'qm.fields.TextField'> db_name>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.TextField'> db_module>,
 <<class 'qm.fields.PythonField'> connection>,
 <<class 'qm.fields.TextField'> db_name>]

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-K.html0000664000076400007640000002611711122067144024306 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

K



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler.GCC-class.html0000664000076400007640000003753511122067147027236 0ustar stefanstefan qm.test.classes.compiler.GCC
Package qm :: Package test :: Package classes :: Module compiler :: Class GCC
[hide private]
[frames] | no frames]

Class GCC

source code

Compiler --+
           |
          GCC

A 'GCC' is a GNU Compiler Collection compiler.

Instance Methods [hide private]
 
ParseOutput(self, output, ignore_regexps=())
Return the 'Diagnostic's indicated in the 'output'.
source code

Inherited from Compiler: Compile, ExecuteCommand, GetCompilationCommand, GetExecutableExtension, GetLDFlags, GetObjectExtension, GetOptions, GetPath, SetLDFlags, SetOptions, __init__

Inherited from Compiler (private): _GetModeSwitches

Class Variables [hide private]
  _severities = ['warning', 'error']
The diagnostic severities generated by the compiler.
  _severity_regexps = {'warning': re.compile('^(?P<file>[^:]*):(...
A map from severities to compiled regular expressions.
  _internal_error_regexp = re.compile('Internal (compiler )?error')
A compiled regular expression.
  MODE_PRECOMPILE = "precompile"
Precompile a header file.
  modes = Compiler.modes+ [MODE_PRECOMPILE]
The available compilation modes.

Inherited from Compiler: MODE_ASSEMBLE, MODE_COMPILE, MODE_LINK, MODE_PREPROCESS

Method Details [hide private]

ParseOutput(self, output, ignore_regexps=())

source code 

Return the 'Diagnostic's indicated in the 'output'.

'output' -- A string giving the output from the compiler.

'ignore_regexps' -- A sequence of regular expressions. If a diagnostic message matches one of these regular expressions, it will be ignored.

returns -- A list of 'Diagnostic's corresponding to the messages indicated in 'output', in the order that they were emitted.

Overrides: Compiler.ParseOutput

Class Variable Details [hide private]

_severities

The diagnostic severities generated by the compiler. Order matters; the order given here is the order that the '_severity_regexps' will be tried.

Value:
['warning', 'error']

_severity_regexps

A map from severities to compiled regular expressions. If the regular expression matches a line in the compiler output, then that line indicates a diagnostic with the indicated severity.

Value:
{'warning': re.compile('^(?P<file>[^:]*):((?P<line>[^:]*):)?' '(\s*(?P\
<column>[0-9]+):)? ' 'warning: (?P<message>.*)$'), 'error': re.compile\
('^(?P<file>[^:]*):((?P<line>[^:]*):)?' '(\s*(?P<column>[0-9]+):)? ' '\
(?P<message>.*)$')}

_internal_error_regexp

A compiled regular expression. When an error message is matched by this regular expression, the error message indicates an internal error in the compiler.

Value:
re.compile('Internal (compiler )?error')

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test.ExecutableTest-class.html0000664000076400007640000004025711122067147033321 0ustar stefanstefan qm.test.classes.compilation_test.ExecutableTest
Package qm :: Package test :: Package classes :: Module compilation_test :: Class ExecutableTest
[hide private]
[frames] | no frames]

Class ExecutableTest

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
                  test.Test --+
                              |
                             ExecutableTest

An ExecuableTest runs an executable from a CompiledResource. ExecutableTest allows simple cross-testing. To run the executable on anything other than localhost, specify a Host descriptor by means of the context variable 'ExecutableTest.host'.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  args = SetField(TextField(description= "Arguments to pass to t...

Inherited from test.Test: PREREQUISITES_FIELD_ID, arguments, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

Overrides: test.Test.Run
(inherited documentation)

Class Variable Details [hide private]

args

Value:
SetField(TextField(description= "Arguments to pass to the executable."\
))

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.platform_unix-module.html0000664000076400007640000000373311122067144026237 0ustar stefanstefan platform_unix

Module platform_unix


Classes

SignalException

Functions

get_host_name
get_signal_name
install_signal_handler
open_in_browser

Variables

default_shell

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dg_test.DGTest-class.html0000664000076400007640000015302611122067147027605 0ustar stefanstefan qm.test.classes.dg_test.DGTest
Package qm :: Package test :: Package classes :: Module dg_test :: Class DGTest
[hide private]
[frames] | no frames]

Class DGTest

source code

         object --+                
                  |                
extension.Extension --+            
                      |            
      runnable.Runnable --+        
                          |        
                  test.Test --+    
                              |    
   dejagnu_base.DejaGNUBase --+    
                              |    
       dejagnu_test.DejaGNUTest --+
                                  |
                                 DGTest

A 'DGTest' is a test using the DejaGNU 'dg' driver.

This test class emulates the 'dg.exp' source file in the DejaGNU distribution.

Nested Classes [hide private]
  DGException
The exception class raised by 'DGTest'.

Inherited from dejagnu_test.DejaGNUTest: BuildExecutable

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
_RunDGTest(self, tool_flags, default_options, context, result, path=None, default_kind=None, keep_output=None)
Run a 'dg' test.
source code
 
_RunDGToolPortion(self, path, tool_flags, context, result)
Perform the tool-running portions of a DG test.
source code
 
_RunDGExecutePortion(self, file, context, result)
Perform the executable-running portions of a DG test.
source code
 
_ExecuteFinalCommand(self, command, args, context, result)
Run a command specified with 'dg-final'.
source code
 
_PruneOutput(self, output)
Remove unintersting messages from 'output'.
source code
 
_RunTool(self, path, kind, options, context, result)
Run the tool being tested.
source code
 
_DGdo(self, line_num, args, context)
Emulate the 'dg-do' command.
source code
 
_DGfinal(self, line_num, args, context)
Emulate the 'dg-final' command.
source code
 
_DGoptions(self, line_num, args, context)
Emulate the 'dg-options' command.
source code
 
_DGbogus(self, line_num, args, context)
Emulate the 'dg-bogus' command.
source code
 
_DGwarning(self, line_num, args, context)
Emulate the 'dg-warning' command.
source code
 
_DGerror(self, line_num, args, context)
Emulate the 'dg-error' command.
source code
 
_DGexcess_errors(self, line_num, args, context)
Emulate the 'dg-excess-errors' command.
source code
 
__ExpectDiagnostic(self, kind, line_num, args, context)
Register an expected diagnostic.
source code
 
_ParseTargetSelector(self, selector, context)
Parse the target 'selector'.
source code

Inherited from dejagnu_test.DejaGNUTest (private): _Error, _GetBuild, _GetSourcePath, _GetTarget, _GetTargetEnvironment, _IsNative, _ParseTclWords, _RecordDejaGNUOutcome, _RunBuildExecutable, _RunTargetExecutable, _SetUp, _Unresolved

Inherited from test.Test: GetTargetGroup, Run

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Inherited from dejagnu_base.DejaGNUBase (private): _RecordCommand, _RecordCommandOutput

Class Variables [hide private]
  __dg_command_regexp = re.compile(r"{[ \t]+dg-([-a-z]+)[ \t]+(....
A regular expression matching commands embedded in the source file.
  KIND_PREPROCESS = "preprocess"
  KIND_COMPILE = "compile"
  KIND_ASSEMBLE = "assemble"
  KIND_LINK = "link"
  KIND_RUN = "run"
  keep_output = BooleanField(default_value= False, description= ...
  _default_kind = "compile"
The default test kind.
  __test_kinds = KIND_PREPROCESS, KIND_COMPILE, KIND_ASSEMBLE, K...
The kinds of tests supported by 'dg.exp'.
  __DIAG_BOGUS = "bogus"
  __DIAG_ERROR = "error"
  __DIAG_WARNING = "warning"
  __diagnostic_descriptions = {__DIAG_ERROR: "errors", __DIAG_WA...
A map from dg diagnostic kinds to descriptive strings.

Inherited from dejagnu_test.DejaGNUTest: ERROR, FAIL, KFAIL, KPASS, PASS, RESULT_PREFIX, UNRESOLVED, UNSUPPORTED, UNTESTED, WARNING, XFAIL, XPASS, arguments, dejagnu_outcomes, executable_timeout, outcome_map

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

_RunDGTest(self, tool_flags, default_options, context, result, path=None, default_kind=None, keep_output=None)

source code 

Run a 'dg' test.

'tool_flags' -- A list of strings giving a set of options to be provided to the tool being tested.

'default_options' -- A list of strings giving a default set of options to be provided to the tool being tested. These options can be overridden by an embedded 'dg-options' command in the test itself.

'context' -- The 'Context' in which this test is running.

'result' -- The 'Result' of the test execution.

'path' -- The path to the test file. If 'None', the main test file path is used.

'default_kind' -- The kind of test to perform. If this value is 'None', then 'self._default_kind' is used.

'keep_output' -- True if the output file should be retained after the test is complete. Otherwise, it is removed.

This function emulates 'dg-test'.

_RunDGToolPortion(self, path, tool_flags, context, result)

source code 

Perform the tool-running portions of a DG test.

Calls '_RunTool' and processes its output.

returns -- The filename of the generated file.

_RunDGExecutePortion(self, file, context, result)

source code 

Perform the executable-running portions of a DG test.

If this is a "run" test, runs the executable generated by the tool and checks its output.

_ExecuteFinalCommand(self, command, args, context, result)

source code 

Run a command specified with 'dg-final'.

'command' -- A string giving the name of the command.

'args' -- A list of strings giving the arguments (if any) to that command.

'context' -- The 'Context' in which this test is running.

'result' -- The 'Result' of this test.

_PruneOutput(self, output)

source code 

Remove unintersting messages from 'output'.

'output' -- A string giving the output from the tool being tested.

returns -- A modified version of 'output'. This modified version does not contain tool output messages that are irrelevant for testing purposes.

_RunTool(self, path, kind, options, context, result)

source code 

Run the tool being tested.

'path' -- The path to the test file.

'kind' -- The kind of test to perform.

'options' -- A list of strings giving command-line options to provide to the tool.

'context' -- The 'Context' for the test execution.

'result' -- The QMTest 'Result' for the test.

returns -- A pair '(output, file)' where 'output' consists of any messages produced by the compiler, and 'file' is the name of the file produced by the compilation, if any.

_DGdo(self, line_num, args, context)

source code 

Emulate the 'dg-do' command.

'line_num' -- The line number at which the command was found.

'args' -- The arguments to the command, as a list of strings.

'context' -- The 'Context' in which the test is running.

_DGfinal(self, line_num, args, context)

source code 

Emulate the 'dg-final' command.

'line_num' -- The line number at which the command was found.

'args' -- The arguments to the command, as a list of strings.

'context' -- The 'Context' in which the test is running.

_DGoptions(self, line_num, args, context)

source code 

Emulate the 'dg-options' command.

'line_num' -- The line number at which the command was found.

'args' -- The arguments to the command, as a list of strings.

'context' -- The 'Context' in which the test is running.

_DGbogus(self, line_num, args, context)

source code 

Emulate the 'dg-bogus' command.

'line_num' -- The number at which the command was found.

'args' -- The arguments to the command, as a list of strings.

'context' -- The 'Context' in which the test is running.

_DGwarning(self, line_num, args, context)

source code 

Emulate the 'dg-warning' command.

'line_num' -- The number at which the command was found.

'args' -- The arguments to the command, as a list of strings.

'context' -- The 'Context' in which the test is running.

_DGerror(self, line_num, args, context)

source code 

Emulate the 'dg-error' command.

'line_num' -- The number at which the command was found.

'args' -- The arguments to the command, as a list of strings.

'context' -- The 'Context' in which the test is running.

_DGexcess_errors(self, line_num, args, context)

source code 

Emulate the 'dg-excess-errors' command.

'line_num' -- The line number at which the command was found.

'args' -- The arguments to the command, as a list of strings.

'context' -- The 'Context' in which the test is running.

__ExpectDiagnostic(self, kind, line_num, args, context)

source code 

Register an expected diagnostic.

'kind' -- The kind of diagnostic expected.

'line_num' -- The number at which the command was found.

'args' -- The arguments to the command, as a list of strings.

'context' -- The 'Context' in which the test is running.

_ParseTargetSelector(self, selector, context)

source code 

Parse the target 'selector'.

'selector' -- A target selector.

'context' -- The 'Context' in which the test is running.

returns -- For a 'target' selector, 'S' if this test should be run, or 'N' if it should not. For an 'xfail' selector, 'F' if the test is expected to fail; 'P' if if not.

This function emulates dg-process-target.


Class Variable Details [hide private]

__dg_command_regexp

A regular expression matching commands embedded in the source file.

Value:
re.compile(r"{[ \t]+dg-([-a-z]+)[ \t]+(.*)[ \t]+}[^}]*$")

keep_output

Value:
BooleanField(default_value= False, description= """True if the output \
file should be retained
        after the test is complete.  Otherwise, it is removed.""")

_default_kind

The default test kind.

This value can be overridden by a 'dg-do' command in the test file.

Value:
"compile"

__test_kinds

The kinds of tests supported by 'dg.exp'.

Value:
KIND_PREPROCESS, KIND_COMPILE, KIND_ASSEMBLE, KIND_LINK, KIND_RUN

__diagnostic_descriptions

A map from dg diagnostic kinds to descriptive strings.

Value:
{__DIAG_ERROR: "errors", __DIAG_WARNING: "warnings", __DIAG_BOGUS: "bo\
gus messages", "build": "build failure",}

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_database.XMLDatabase-class.html0000664000076400007640000011523311122067150031523 0ustar stefanstefan qm.test.classes.xml_database.XMLDatabase
Package qm :: Package test :: Package classes :: Module xml_database :: Class XMLDatabase
[hide private]
[frames] | no frames]

Class XMLDatabase

source code

         object --+                
                  |                
extension.Extension --+            
                      |            
      database.Database --+        
                          |        
 file_database.FileDatabase --+    
                              |    
file_database.ExtensionDatabase --+
                                  |
                                 XMLDatabase

A database representing tests as XML files in a directory tree.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, path, arguments)
Construct a 'Database'.
source code
 
_GetTestFromPath(self, test_id, test_path)
Return a descriptor for the test given by 'path'.
source code
 
_GetResourceFromPath(self, resource_id, resource_path)
Return a descriptor for the resource given by 'path'.
source code
 
__StoreAttachments(self, item)
Store all attachments in 'item' in the attachment store.
source code
 
__MakeDataFilePath(self, item_id, file_name)
Construct the path to an attachment data file.
source code
 
__LoadItem(self, item_id, path, document_parser)
Load an item (a test or resource) from an XML file.
source code
 
__ParseTestDocument(self, test_id, document)
Return a test object constructed from a test document.
source code
 
__ParseResourceDocument(self, resource_id, document)
Return a resource object constructed from a resource document.
source code
 
_GetSuiteFromPath(self, suite_id, path)
Load the test suite file at 'path' with suite ID 'suite_id'.
source code
 
WriteExtension(self, id, extension)
Store 'extension' in the database, using the name 'id'.
source code
 
GetAttachmentStore(self)
Returns the 'AttachmentStore' associated with the database.
source code
 
_Trace(self, message)
Write a trace 'message'.
source code

Inherited from file_database.ExtensionDatabase: GetResourceExtension, GetResourcePath, GetSuiteExtension, GetSuitePath, GetTestExtension, GetTestPath

Inherited from file_database.ExtensionDatabase (private): _GetLabelFromBasename, _GetPathFromLabel, _GetRelativeLabelPath, _IsResourceFile, _IsSuiteFile, _IsTestFile

Inherited from file_database.FileDatabase: GetIds, GetResource, GetRoot, GetSubdirectories, GetSuite, GetTest, RemoveExtension

Inherited from file_database.FileDatabase (private): _AreLabelsPaths, _GetLabels, _GetPath, _IsFile

Inherited from database.Database: ExpandIds, GetClassPaths, GetConfigurationDirectory, GetExtension, GetExtensions, GetItem, GetLabelComponents, GetPath, GetResourceClassNames, GetResourceIds, GetSuiteIds, GetTestClassNames, GetTestIds, HasResource, HasSuite, HasTest, IsModifiable, IsValidLabel, JoinLabels, SplitLabel, SplitLabelLeft

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from file_database.ExtensionDatabase: arguments

Inherited from database.Database: ITEM_KINDS, RESOURCE, SUITE, TEST, kind, label_class, modifiable

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, path, arguments)
(Constructor)

source code 

Construct a 'Database'.

'path' -- A string containing the absolute path to the directory containing the database.

'arguments' -- A dictionary mapping attribute names to values. The use of this parameter is deprecated. Use keyword arguments instead.

Derived classes must call this method from their own '__init__' methods. Every derived class must have an '__init__' method that takes the path to the directory containing the database as its only argument. The path provided to the derived class '__init__' function will always be an absolute path.

Overrides: object.__init__
(inherited documentation)

_GetTestFromPath(self, test_id, test_path)

source code 

Return a descriptor for the test given by 'path'.

'test_id' -- The label naming the test.

'path' -- An absolute path to a test file. The 'path' satisfies '_IsTestFile'.

returns -- A 'TestDescriptor' corresponding to 'test_id'.

Derived classes must override this method.

Overrides: file_database.FileDatabase._GetTestFromPath
(inherited documentation)

_GetResourceFromPath(self, resource_id, resource_path)

source code 

Return a descriptor for the resource given by 'path'.

'resource_id' -- The label naming the resource.

'path' -- An absolute path to a resource file. The 'path' satisfies '_IsResourceFile'.

returns -- A 'ResourceDescriptor' corresponding to 'resource_id'.

Derived classes must override this method.

Overrides: file_database.FileDatabase._GetResourceFromPath
(inherited documentation)

__StoreAttachments(self, item)

source code 

Store all attachments in 'item' in the attachment store.

'item' -- A 'Test' or 'Resource'. If any of its fields contain attachments, add them to the 'AttachmentStore'.

__MakeDataFilePath(self, item_id, file_name)

source code 

Construct the path to an attachment data file.

'item_id' -- The test or resource item of which the attachment is part.

'file_name' -- The file name specified for the attachment.

__LoadItem(self, item_id, path, document_parser)

source code 

Load an item (a test or resource) from an XML file.

This function is used for logic common to tests and resources.

'item_id' -- The ID of the item to get.

'path' -- The path to the test or resource file.

'document_parser' -- A function that takes an XML DOM document as its argument and returns the constructed item object.

__ParseTestDocument(self, test_id, document)

source code 

Return a test object constructed from a test document.

'test_id' -- The test ID of the test.

'document' -- A DOM document containing a single test element from which the test is constructed.

__ParseResourceDocument(self, resource_id, document)

source code 

Return a resource object constructed from a resource document.

'resource_id' -- The resource ID of the resource.

'document' -- A DOM document node containing a single resource element from which the resource object is constructed.

_GetSuiteFromPath(self, suite_id, path)

source code 

Load the test suite file at 'path' with suite ID 'suite_id'.

returns -- A 'Suite' object.

Overrides: file_database.FileDatabase._GetSuiteFromPath

WriteExtension(self, id, extension)

source code 

Store 'extension' in the database, using the name 'id'.

'id' -- A label for the 'extension'.

'extension' -- An instance of 'Extension'.

The 'extension' is stored in the database. If there is a previous item in the database with the same id, it is removed and replaced with 'extension'. Some databases may not be able to store all 'Extension' instances; those database must throw an exception when an attempt is made to store such an 'extension'.

Overrides: database.Database.WriteExtension
(inherited documentation)

GetAttachmentStore(self)

source code 

Returns the 'AttachmentStore' associated with the database.

returns -- The 'AttachmentStore' containing the attachments associated with tests and resources in this database.

Overrides: database.Database.GetAttachmentStore

_Trace(self, message)

source code 

Write a trace 'message'.

'message' -- A string to be output as a trace message.


qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-Y.html0000664000076400007640000001054411122067144024321 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_String-module.html0000664000076400007640000001461711122067145031520 0ustar stefanstefan qm.external.DocumentTemplate.DT_String
Package qm :: Package external :: Package DocumentTemplate :: Module DT_String
[hide private]
[frames] | no frames]

Module DT_String

source code

$Id: DT_String.py 40317 2005-11-22 15:14:40Z tseaver $

Classes [hide private]
  String
Document templates defined from strings.
  FileMixin
  File
Document templates read from files.
Variables [hide private]
  _marker = []
././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_result_stream.XMLResultReader-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_result_stream.XMLResultReader-class.ht0000664000076400007640000004634711122067150033225 0ustar stefanstefan qm.test.classes.xml_result_stream.XMLResultReader
Package qm :: Package test :: Package classes :: Module xml_result_stream :: Class XMLResultReader
[hide private]
[frames] | no frames]

Class XMLResultReader

source code

                 object --+            
                          |            
        extension.Extension --+        
                              |        
     result_reader.ResultReader --+    
                                  |    
file_result_reader.FileResultReader --+
                                      |
                                     XMLResultReader

Reads in 'Result's from an XML-formatted results file.

To write such a file, see 'XMLResultStream'.

Nested Classes [hide private]

Inherited from file_result_reader.FileResultReader: InvalidFile

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'FileResultReader'.
source code
 
GetAnnotations(self)
Return this run's dictionary of annotations.
source code
 
GetResult(self)
Return the next 'Result' from this reader.
source code
 
_GetResultFromDomNode(self, node)
Extract a result from a DOM node.
source code

Inherited from result_reader.ResultReader: __iter__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from file_result_reader.FileResultReader: arguments, file, filename

Inherited from result_reader.ResultReader: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'FileResultReader'.

'arguments' -- As for 'ResultReader'.

If the file provided is not in the input format expected by this result reader, the derived class '__init__' function must raise an 'InvalidStream' exception.

Overrides: object.__init__
(inherited documentation)

GetAnnotations(self)

source code 

Return this run's dictionary of annotations.

Overrides: result_reader.ResultReader.GetAnnotations
(inherited documentation)

GetResult(self)

source code 

Return the next 'Result' from this reader.

returns -- A 'Result', or 'None' if there are no more results.

Overrides: result_reader.ResultReader.GetResult
(inherited documentation)

_GetResultFromDomNode(self, node)

source code 

Extract a result from a DOM node.

'node' -- A DOM node corresponding to a "result" element.

returns -- A 'Result' object.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test_database-pysrc.html0000664000076400007640000040113611122067153032252 0ustar stefanstefan qm.test.classes.compilation_test_database
Package qm :: Package test :: Package classes :: Module compilation_test_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.compilation_test_database

  1  ######################################################################## 
  2  # 
  3  # File:   compilation_test_database.py 
  4  # Author: Stefan Seefeld 
  5  # Date:   2006-07-28 
  6  # 
  7  # Contents: 
  8  #   CompilationTestDatabase. 
  9  # 
 10  # Copyright (c) 2006 by CodeSourcery, Inc.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import os, dircache 
 21  from   qm.common import parse_string_list 
 22  from   qm.extension import get_class_arguments 
 23  from   qm.fields import * 
 24  import qm.label 
 25  import qm.structured_text 
 26  import qm.test.base 
 27  from   qm.test.database import * 
 28  from   qm.test.suite import * 
 29  from   qm.test import context 
 30  from   qm.test.classes.explicit_suite import ExplicitSuite 
 31  from   qm.test.classes import compilation_test 
 32  from   qm.test.classes.compiler import Compiler 
 33  from   qm.test.classes.compiler_test import CompilationStep 
 34  from   qm.test.classes.compiler_table import CompilerTable 
 35   
 36  ######################################################################## 
 37  # classes 
 38  ######################################################################## 
 39   
40 -class CompilationTest(compilation_test.CompilationTest):
41 """A CompilationTest fetches compilation parameters from environment 42 variables CPPFLAGS, <lang>_options, and <lang>_ldflags in addition 43 to the CompilerTable-related parameters.""" 44 45 options = SetField(TextField(), computed="true") 46 ldflags = SetField(TextField(), computed="true") 47 source_files = SetField(TextField(), computed="true") 48 executable = TextField(computed="true") 49 language = TextField() 50 51
52 - def _GetCompilationSteps(self, c):
53 54 lang = self.language 55 compiler = c['CompilerTable.compilers'][lang] 56 label_components = self.GetDatabase().GetLabelComponents(self.GetId()) 57 label_components[-1] = os.path.splitext(label_components[-1])[0] 58 selector = '.'.join(label_components) 59 path = c.GetDerivedValue(selector, lang + '_path') 60 if path: 61 compiler = Compiler(path, compiler.GetOptions(), compiler.GetLDFlags()) 62 options = (parse_string_list(c.GetDerivedValue( 63 selector, 'CPPFLAGS', '')) + 64 parse_string_list(c.GetDerivedValue( 65 selector, lang + '_options', ''))) 66 ldflags = (parse_string_list(c.GetDerivedValue( 67 selector, lang + '_ldflags', ''))) 68 69 return [CompilationStep(compiler, 70 Compiler.MODE_LINK, self.source_files, 71 self.options + options, 72 self.ldflags + ldflags, 73 self.executable, [])]
74 75
76 -class CompilationTestDatabase(Database):
77 """A 'CompilationTestDatabase' test database maps source code files to 78 compilation tests.""" 79 80 srcdir = TextField(title = "Source Directory", 81 description = "The root of the test suite's source tree.") 82 excluded_subdirs = SetField(TextField(), 83 default_value = ['QMTest', 'CVS', '.svn', 'build']) 84 test_extensions = DictionaryField(TextField(), 85 EnumerationField(enumerals = ['c', 'cplusplus']), 86 default_value = {'.c':'c', 87 '.cpp':'cplusplus', 88 '.cxx':'cplusplus', 89 '.cc':'cplusplus', 90 '.C':'cplusplus', 91 '.f':'fortran'}) 92 _is_generic_database = True 93 94
95 - def __init__(self, path, arguments):
96 97 self.label_class = "file_label.FileLabel" 98 self.modifiable = "false" 99 # Initialize the base class. 100 super(CompilationTestDatabase, self).__init__(path, **arguments)
101 102
103 - def GetSubdirectories(self, directory):
104 105 dirname = os.path.join(self.srcdir, directory) 106 return [subdir for subdir in dircache.listdir(dirname) 107 if (os.path.isdir(os.path.join(dirname, subdir)) and 108 subdir not in self.excluded_subdirs)]
109 110
111 - def GetIds(self, kind, directory = '', scan_subdirs = 1):
112 113 dirname = os.path.join(self.srcdir, directory) 114 if not os.path.isdir(dirname): 115 raise NoSuchSuiteError, directory 116 117 if kind == Database.TEST: 118 ids = [self.JoinLabels(directory, f) 119 for f in dircache.listdir(dirname) 120 if (os.path.isfile(os.path.join(dirname, f)) and 121 os.path.splitext(f)[1] in self.test_extensions)] 122 123 elif kind == Database.RESOURCE: 124 ids = [] 125 126 else: # SUITE 127 ids = [self.JoinLabels(directory, d) 128 for d in self.GetSubdirectories(directory) 129 if d not in self.excluded_subdirs] 130 131 if scan_subdirs: 132 for subdir in dircache.listdir(dirname): 133 if (subdir not in self.excluded_subdirs 134 and os.path.isdir(os.path.join(dirname, subdir))): 135 dir = self.JoinLabels(directory, subdir) 136 ids.extend(self.GetIds(kind, dir, True)) 137 138 return ids
139 140
141 - def GetExtension(self, id):
142 143 if not id: 144 return DirectorySuite(self, id) 145 146 elif id == 'compiler_table': 147 return CompilerTable({}, 148 qmtest_id = id, 149 qmtest_database = self) 150 151 id_components = self.GetLabelComponents(id) 152 file_ext = os.path.splitext(id_components[-1])[1] 153 if (file_ext in self.test_extensions and 154 os.path.isfile(os.path.join(self.srcdir, id))): 155 return self._MakeTest(id, self.test_extensions[file_ext]) 156 157 elif os.path.isdir(os.path.join(self.srcdir, id)): 158 basename = os.path.basename(id) 159 if not basename in self.excluded_subdirs: 160 return DirectorySuite(self, id) 161 162 else: 163 return None
164 165
166 - def _MakeTest(self, test_id, language):
167 168 169 src = os.path.abspath(os.path.join(self.srcdir, test_id)) 170 # Construct a unique name for the executable as it may be 171 # kept for failure analysis. 172 executable = os.path.splitext(os.path.basename(test_id))[0] 173 if sys.platform == 'win32': 174 executable += '.exe' 175 176 resources = ['compiler_table'] 177 arguments = {} 178 arguments['language'] = language 179 arguments['source_files'] = [src] 180 arguments['executable'] = executable 181 arguments['resources'] = resources 182 183 return CompilationTest(arguments, 184 qmtest_id = test_id, 185 qmtest_database = self)
186

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command-module.html0000664000076400007640000001315011122067145026610 0ustar stefanstefan qm.test.classes.command
Package qm :: Package test :: Package classes :: Module command
[hide private]
[frames] | no frames]

Module command

source code

Classes [hide private]
  ExecTestBase
Check a program's output and exit code.
  ExecTest
Check a program's output and exit code.
  ShellCommandTest
Check a shell command's output and exit code.
  ShellScriptTest
Check a shell script's output and exit code.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_Raise-module.html0000664000076400007640000000235611122067144032074 0ustar stefanstefan DT_Raise

Module DT_Raise


Classes

Raise

Variables

__rcs_id__

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.file_result_stream-module.html0000664000076400007640000000216411122067144030213 0ustar stefanstefan file_result_stream

Module file_result_stream


Classes

FileResultStream

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result_reader-pysrc.html0000664000076400007640000014315311122067162026257 0ustar stefanstefan qm.test.result_reader
Package qm :: Package test :: Module result_reader
[hide private]
[frames] | no frames]

Source Code for Module qm.test.result_reader

 1  ######################################################################## 
 2  # 
 3  # File:   result_reader.py 
 4  # Author: Nathaniel Smith 
 5  # Date:   2003-06-23 
 6  # 
 7  # Contents: 
 8  #   QMTest ResultReader class. 
 9  # 
10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  import qm.extension 
21   
22  ######################################################################## 
23  # Classes 
24  ######################################################################## 
25   
26 -class ResultReader(qm.extension.Extension):
27 """A 'ResultReader' provides access to stored test results. 28 29 For instance, a 'ResultReader' may load 'Result's from a pickle 30 file or an XML file. 31 32 This is an abstract class. 33 34 See also 'ResultStream'.""" 35 36 kind = "result_reader" 37
38 - def __init__(self, arguments, **args):
39 40 if arguments: args.update(arguments) 41 super(ResultReader, self).__init__(**args)
42 43
44 - def GetAnnotations(self):
45 """Return this run's dictionary of annotations.""" 46 47 # For backwards compatibility, don't raise an exception. 48 return {}
49 50
51 - def GetResult(self):
52 """Return the next 'Result' from this reader. 53 54 returns -- A 'Result', or 'None' if there are no more results. 55 """ 56 57 raise NotImplementedError
58 59
60 - def __iter__(self):
61 """A 'ResultReader' can be iterated over.""" 62 63 return iter(self.GetResult, None)
64 65 ######################################################################## 66 # Local Variables: 67 # mode: python 68 # indent-tabs-mode: nil 69 # fill-column: 72 70 # End: 71

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user-module.html0000664000076400007640000005512211122067145023543 0ustar stefanstefan qm.user
Package qm :: Module user
[hide private]
[frames] | no frames]

Module user

source code

User management facilities.

Access to this module is primarily through two global variables.

  'database' -- The user database.  The database contains objects
  representing users, accessed via a *user ID*.  The user ID is a label
  uniquely identifying the user in the system.

  The user database also provides a notion of user groups.  Each group
  is identified by a group ID, and contains zero or more user IDs.  A
  user may belong to more than one group.  A group may not contain other
  groups. 

  'authenticator' -- The authenticator object by which the application
  authenticates users who attempt to access it via various channels.

Access the database object via this interface:

  * Use the database object as a Python map from user IDs to 'User'
    objects.  The 'keys' method returns a sequence of user IDs in the
    database. 

  * Call 'GetGroupIds' to return a sequence of group IDs.  Use the
    'GetGroup' method to retrieve a 'Group' object for a given group ID.

Classes [hide private]
  AuthenticationError
  XmlDatabaseError
  AccountDisabledError
  User
A user account record.
  Group
A group of users.
  Authenticator
Base class for authentication classes.
  DefaultDatabase
  DefaultAuthenticator
Authenticator for only a single user, "default_user".
  XmlDatabase
An XML user database.
  XmlDatabaseAuthenticator
An authenticator based on contents of the XML user database.
Functions [hide private]
 
load_xml_database(path)
Load users from XML database at 'path' and set up authenticator.
source code
 
get_user_from_dom(user_node)
Construct a 'User' object from a user DOM element.
source code
 
_get_dom_properties(node, tag)
Return a dictionary of properties from a user DOM element node.
source code
 
create_dom_for_user(document, user)
Create a DOM element node for 'user'.
source code
 
_create_dom_properties(element, properties)
Add user properties to a DOM element.
source code
 
get_group_from_dom(group_node)
Construct a 'Group' object from a DOM element.
source code
 
create_dom_for_group(document, group)
Create a DOM element node for 'group'.
source code
Variables [hide private]
  xml_user_database_dtd = '-//Software Carpentry//User Database ...
  database = DefaultDatabase()
  authenticator = DefaultAuthenticator()
Function Details [hide private]

get_user_from_dom(user_node)

source code 

Construct a 'User' object from a user DOM element.

'user_node' -- A "user" DOM element.

returns -- A 'User' object.

_get_dom_properties(node, tag)

source code 

Return a dictionary of properties from a user DOM element node.

'node' -- A "user" DOM element.

'tag' -- The tag of the child element in which to look for properties.

returns -- A map from property names to values.

create_dom_for_user(document, user)

source code 

Create a DOM element node for 'user'.

'document' -- The DOM document object in which to create the element.

'user' -- A 'User' instance.

returns -- A DOM element node.

_create_dom_properties(element, properties)

source code 

Add user properties to a DOM element.

'element' -- A DOM element node to which properties are to be added as children.

'properties' -- A map from property names to values.

get_group_from_dom(group_node)

source code 

Construct a 'Group' object from a DOM element.

'group_node' -- A DOM "group" element node.

returns -- A 'Group' object.

create_dom_for_group(document, group)

source code 

Create a DOM element node for 'group'.

'document' -- The DOM document object in which to create the element.

'group' -- A 'Group' instance.

returns -- A DOM element node.


Variables Details [hide private]

xml_user_database_dtd

Value:
'-//Software Carpentry//User Database V0.1//EN'

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test-module.html0000664000076400007640000002371111122067145024521 0ustar stefanstefan qm.test.test
Package qm :: Package test :: Module test
[hide private]
[frames] | no frames]

Module test

source code

Classes [hide private]
  TargetGroupField
A 'TargetGroupField' contains a target group pattern.
  Test
A 'Test' is run to check for correct behavior.
Functions [hide private]
 
set_targets(targets)
Set the available target.
source code
 
get_targets()
Get the available target.
source code
Variables [hide private]
  __the_targets = []
The global set of available targets.
Function Details [hide private]

set_targets(targets)

source code 

Set the available target.

'targets' -- A list of targets available for test execution.

get_targets()

source code 

Get the available target.

returns -- A list of targets available for test execution.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database-pysrc.html0000664000076400007640000060345011122067157027230 0ustar stefanstefan qm.test.parameter_database
Package qm :: Package test :: Module parameter_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.parameter_database

  1  ######################################################################## 
  2  # 
  3  # File:   parameter_database.py 
  4  # Author: Stefan Seefeld 
  5  # Date:   2005-01-17 
  6  # 
  7  # Contents: 
  8  #   Test database that parametrizes another test database.. 
  9  # 
 10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  from qm.test.database import * 
 21  from qm.test.suite import * 
 22   
 23  ######################################################################## 
 24  # classes 
 25  ######################################################################## 
 26   
27 -class ParameterDatabase(Database):
28 """A database that parametrizes another database. 'Parameter' in this 29 context refers to any name that is used as a label, and which stands 30 for a specific set of arguments passed to tests. 31 32 The 'ParameterDatabase' class is abstract. Subclasses need to implement 33 the '_GetParametersForTest' as well as the '_GetArgumentsForParameter' 34 method. 35 """ 36
37 - class ImplicitSuite(Suite):
38 """ImplicitSuite represents a suite obtained from a test and a set 39 of parameters applied to it.""" 40
41 - def __init__(self, db, suite_id):
42 43 Suite.__init__(self, {}, 44 qmtest_id = suite_id, 45 qmtest_database = db)
46 47
48 - def GetTestIds(self):
49 50 database = self.GetDatabase() 51 id = self.GetId() 52 return map(lambda p, db = database, id = id: db.JoinLabels(id, p), 53 database._GetParametersForTest(id))
54 55
56 - def IsImplicit(self):
57 58 return True
59 60
61 - class WrapperSuite(Suite):
62 """As tests from the wrapped Database are mapped to suites, suites 63 from the wrapped Database have to be recreated with all tests 64 replaced by ImplicitSuite instances. Additionally, new (explicit) 65 suites may be added.""" 66
67 - def __init__(self, db, suite, suite_ids = None):
68 """Take over suite_ids from the wrapped database but replace 69 test_ids by suite_ids if there are parameters available for 70 them.""" 71 72 Suite.__init__(self, {}, 73 qmtest_id = suite.GetId(), 74 qmtest_database = db) 75 self.__suite = suite 76 self.__suite_ids = suite_ids or []
77 78
79 - def GetSuiteIds(self):
80 81 suite_ids = self.__suite.GetSuiteIds() 82 for t in self.__suite.GetTestIds(): 83 if self.GetDatabase()._GetParametersForTest(t): 84 suite_ids.append(t) 85 return suite_ids + self.__suite_ids
86 87
88 - def GetTestIds(self):
89 90 test_ids = [] 91 for t in self.__suite.GetTestIds(): 92 if not self.GetDatabase()._GetParametersForTest(t): 93 test_ids.append(t) 94 return test_ids
95 96
97 - def IsImplicit(self):
98 99 return self.__suite.IsImplicit()
100 101
102 - def GetAllTestAndSuiteIds(self):
103 104 db = self.GetDatabase() 105 orig_test_ids, suite_ids = self.__suite.GetAllTestAndSuiteIds() 106 test_ids = [] 107 for test in orig_test_ids: 108 parameters = db._GetParametersForTest(test) 109 if parameters: 110 suite_ids.append(test) 111 test_ids.extend(map(lambda p, test=test, db=db: 112 db.JoinLabels(test, p), 113 parameters)) 114 else: 115 test_ids.append(test) 116 return test_ids, suite_ids + self.__suite_ids
117 118
119 - class ParameterSuite(Suite):
120 """ParameterSuite represents a suite obtained from applying a 121 given parameter to a suite from the wrapped DB.""" 122
123 - def __init__(self, database, suite, parameter):
124 """Construct a ParameterSuite. 125 126 database -- The database this suite refers to. 127 128 suite -- The original suite this suite parametrizes. 129 130 parameter -- The value for the parameter to apply to the suite.""" 131 132 Suite.__init__(self, {}, 133 qmtest_id = database.JoinLabels(suite.GetId(), 134 parameter), 135 qmtest_database = database) 136 self.__suite = suite 137 self.__parameter = parameter
138 139
140 - def GetSuiteIds(self):
141 """ParameterSuites contain ParameterSuites which wrap suites 142 contained in the wrapped suite.""" 143 144 database = self.GetDatabase() 145 return map(lambda id, db = database, p = self.__parameter: 146 db.JoinLabels(id, p), self.__suite.GetSuiteIds())
147 148
149 - def GetTestIds(self):
150 """ParameterSuites contain Tests obtained by applying the given 151 parameter set to the tests contained in the wrapped suite.""" 152 153 database = self.GetDatabase() 154 return map(lambda id, db = database, p = self.__parameter: 155 db.JoinLabels(id, p), self.__suite.GetTestIds())
156 157
158 - def IsImplicit(self):
159 160 return False
161 162
163 - def __init__(self, database, path, arguments):
164 165 self.label_class = database.label_class 166 Database.__init__(self, path, arguments) 167 self.__db = database
168 169
170 - def GetWrappedDatabase(self):
171 172 return self.__db
173 174
175 - def _GetParametersForTest(self, test_id):
176 """Return a list of parameters that can be applied to the test 177 'test_id'.""" 178 179 return []
180 181
182 - def _GetArgumentsForParameter(self, test_id, parameter):
183 """Return the set of arguments for this parameter. 184 185 'test_id' -- The test id to which the parameter belongs. 186 187 'parameter' -- The parameter for which the arguments are queried. 188 189 returns -- A dictionary containing the argument as name/value pairs.""" 190 191 return {}
192 193
194 - def GetTest(self, test_id):
195 196 directory, basename = self.SplitLabel(test_id) 197 198 if not self.HasTest(test_id): 199 raise NoSuchTestError, test_id 200 201 test = self.__db.GetTest(directory) 202 # now generate a new test 203 arguments = test.GetArguments() 204 205 #override parameters 206 arguments.update(self._GetArgumentsForParameter(directory, basename)) 207 return TestDescriptor(self, test_id, test.GetClassName(), 208 arguments)
209
210 - def HasTest(self, test_id):
211 212 # If test_id is a parametrized test, its basename has to refer to 213 # a parameter set and the directory to a test in the wrapped DB. 214 # 215 # Else basename must not be a parameter set, and test_id a test 216 # in the wrapped DB. 217 218 directory, basename = self.SplitLabel(test_id) 219 220 return (basename in self._GetParametersForTest(directory) 221 and self.__db.HasTest(directory) 222 or self.__db.HasTest(test_id))
223 224
225 - def GetTestIds(self, directory="", scan_subdirs=1):
226 227 # directory may be a test in the wrapped DB... 228 if self.__db.HasTest(directory): 229 ids = [directory] 230 # ...or a directory, in which case we only take it into account 231 # if scan_subdirs == 1. 232 elif scan_subdirs: 233 ids = self.__db.GetTestIds(directory, scan_subdirs) 234 else: 235 return [] 236 237 tests = [] 238 for p in self._GetParametersForTest(directory): 239 tests += map(lambda x, p = p, db = self: db.JoinLabels(x, p), 240 ids) 241 return tests
242 243
244 - def GetSuite(self, suite_id):
245 246 # If suite_id refers to a suite in the WD, wrap it. 247 if self.__db.HasSuite(suite_id): 248 return ParameterDatabase.WrapperSuite(self, 249 self.__db.GetSuite(suite_id)) 250 251 # If suite_id refers to a test in the WD, parametrize it. 252 elif self.__db.HasTest(suite_id): 253 return ParameterDatabase.ImplicitSuite(self, suite_id) 254 255 raise NoSuchSuiteError, suite_id
256 257
258 - def HasSuite(self, suite_id):
259 260 directory, basename = self.SplitLabel(suite_id) 261 return (basename in self._GetParametersForTest(directory) 262 and self.__db.HasSuite(directory) 263 or self.__db.HasSuite(suite_id) 264 or self.__db.HasTest(suite_id))
265 266
267 - def GetSuiteIds(self, directory="", scan_subdirs=1):
268 269 if self.__db.HasTest(directory): 270 return [] 271 272 suite_ids = self.__db.GetSuiteIds(directory, scan_subdirs) 273 test_ids = self.__db.GetTestIds(directory, scan_subdirs) 274 param_ids = map(lambda p, d = directory, db = self: 275 db.JoinLabels(d, p), 276 self._GetParametersForTest(directory)) 277 278 # The set of all (non-recursive) suite ids is composed of the 279 # original suite ids plus original test ids (now being suite ids) 280 # as well as explicit suites obtained by combining the given 281 # directory with all parameters. 282 ids = suite_ids + test_ids + param_ids 283 if not scan_subdirs: 284 return ids 285 else: 286 # The set of all suite ids is composed of the set above plus 287 # everything above combined with all parameters. 288 expl_ids = [] 289 for p in self._GetParametersForTest(directory): 290 expl_ids += map(lambda x, p = p, db = self: 291 db.JoinLabels(x, p), suite_ids + test_ids) 292 return ids + expl_ids
293 294
295 - def GetResource(self, resource_id):
296 297 return self.__db.GetResource(resource_id)
298 299
300 - def HasResource(self, resource_id):
301 302 return self.__db.HasResource(resource_id)
303 304
305 - def GetResourceIds(self, directory="", scan_subdirs=1):
306 307 if self.__db.HasTest(directory): 308 return [] 309 310 return self.__db.GetResourceIds(directory, scan_subdirs)
311 312
313 - def GetIds(self, kind, directory="", scan_subdirs = 1):
314 315 if kind == Database.TEST: 316 return GetTestIds(directory, scan_subdirs) 317 318 return self.__db.GetIds(kind, directory, scan_subdirs)
319 320
321 - def GetSubdirectories(self, directory):
322 323 # GetSubdirectories returns the subdirectories of the given directory. 324 # As this Database turns all tests from the wrapped Database into 325 # ImplicitSuites, we have to account for them here. 326 # 327 # Further, while 'directory' has to be a directory when looked at it 328 # from this Database, it may well be a test in the context of the wrapped 329 # Database, in which case it can't have subdirectories. 330 if self.__db.HasTest(directory): 331 return [] 332 333 subdirs = self.__db.GetSubdirectories(directory) 334 subdirs += [d[directory and len(directory) + 1:] # Remove common prefix. 335 for d in self.__db.GetTestIds(directory, False)] 336 return subdirs
337 338
339 - def GetAttachmentStore(self):
340 341 return self.__db.GetAttachmentStore()
342 343
344 - def GetClassPath(self):
345 346 return self.__db.GetClassPath()
347 348
349 - def GetTestClassNames(self):
350 351 return self.__db.GetTestClassNames()
352 353
354 - def GetResourceClassNames(self):
355 356 return self.__db.GetResourceClassNames()
357

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.SetExpectationPage-class.html0000664000076400007640000003302611122067151030443 0ustar stefanstefan qm.test.web.web.SetExpectationPage
Package qm :: Package test :: Package web :: Module web :: Class SetExpectationPage
[hide private]
[frames] | no frames]

Class SetExpectationPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      SetExpectationPage

DTML page for setting the expectation associated with a test.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, id)
Construct a new 'SetExpectationPage'.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, id)
(Constructor)

source code 

Construct a new 'SetExpectationPage'.

'server' -- The 'QMTestServer' creating this page.

'id' -- The name of the test whose expectation is being set.

Overrides: web.DtmlPage.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_If-pysrc.html0000664000076400007640000020353611122067161030461 0ustar stefanstefan qm.external.DocumentTemplate.DT_If
Package qm :: Package external :: Package DocumentTemplate :: Module DT_If
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_If

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  __doc__='''Conditional insertion 
 14   
 15         Conditional insertion is performed using 'if' and 'else' 
 16         commands. 
 17   
 18         To include text when an object is true using the EPFS 
 19         format, use:: 
 20   
 21            %(if name)[ 
 22                 text 
 23            %(if name)] 
 24   
 25         To include text when an object is true using the HTML 
 26         format, use:: 
 27   
 28            <!--#if name--> 
 29                 text 
 30            <!--#/if name--> 
 31   
 32         where 'name' is the name bound to the object. 
 33   
 34         To include text when an object is false using the EPFS 
 35         format, use:: 
 36   
 37            %(else name)[ 
 38                 text 
 39            %(else name)] 
 40   
 41         To include text when an object is false using the HTML 
 42         format, use:: 
 43   
 44            <!--#else name--> 
 45                 text 
 46            <!--#/else name--> 
 47   
 48         Finally to include text when an object is true and to 
 49         include different text when the object is false using the 
 50         EPFS format, use:: 
 51   
 52            %(if name)[ 
 53                 true text 
 54            %(if name)] 
 55            %(else name)[ 
 56                 false text 
 57            %(else name)] 
 58   
 59         and to include text when an object is true and to 
 60         include different text when the object is false using the 
 61         HTML format, use:: 
 62   
 63            <!--#if name--> 
 64                 true text 
 65            <!--#else name--> 
 66                 false text 
 67            <!--#/if name--> 
 68   
 69         Notes: 
 70   
 71         - if a variable is nor defined, it is considered to be false. 
 72   
 73         - A variable if only evaluated once in an 'if' tag.  If the value 
 74           is used inside the tag, including in enclosed tags, the 
 75           variable is not reevaluated. 
 76   
 77  ''' 
 78  __rcs_id__='$Id: DT_If.py 1069 2008-11-13 21:55:43Z stefan $' 
 79  __version__='$Revision: 1069 $'[11:-2] 
 80   
 81  from DT_Util import ParseError, parse_params, name_param, str 
 82   
83 -class If:
84 blockContinuations='else','elif' 85 name='if' 86 elses=None 87 expr='' 88
89 - def __init__(self, blocks):
90 91 tname, args, section = blocks[0] 92 args=parse_params(args, name='', expr='') 93 name,expr=name_param(args,'if',1) 94 self.__name__= name 95 if expr is None: cond=name 96 else: cond=expr.eval 97 sections=[cond, section.blocks] 98 99 if blocks[-1][0]=='else': 100 tname, args, section = blocks[-1] 101 del blocks[-1] 102 args=parse_params(args, name='') 103 if args: 104 ename,expr=name_param(args,'else',1) 105 if ename != name: 106 raise ParseError, ('name in else does not match if', 'in') 107 elses=section.blocks 108 else: elses=None 109 110 for tname, args, section in blocks[1:]: 111 if tname=='else': 112 raise ParseError, ( 113 'more than one else tag for a single if tag', 'in') 114 args=parse_params(args, name='', expr='') 115 name,expr=name_param(args,'elif',1) 116 if expr is None: cond=name 117 else: cond=expr.eval 118 sections.append(cond) 119 sections.append(section.blocks) 120 121 if elses is not None: sections.append(elses) 122 123 self.simple_form=tuple(sections)
124
125 -class Unless:
126 name='unless' 127 blockContinuations=() 128
129 - def __init__(self, blocks):
130 tname, args, section = blocks[0] 131 args=parse_params(args, name='', expr='') 132 name,expr=name_param(args,'unless',1) 133 if expr is None: cond=name 134 else: cond=expr.eval 135 self.simple_form=(cond,None,section.blocks)
136
137 -class Else(Unless):
138 # The else tag is included for backward compatibility and is deprecated. 139 name='else'
140

././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.previous_testrun.PreviousTestRun-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.previous_testrun.PreviousTestRun-class.htm0000664000076400007640000004162211122067147033445 0ustar stefanstefan qm.test.classes.previous_testrun.PreviousTestRun
Package qm :: Package test :: Package classes :: Module previous_testrun :: Class PreviousTestRun
[hide private]
[frames] | no frames]

Class PreviousTestRun

source code

                          object --+        
                                   |        
                 extension.Extension --+    
                                       |    
expectation_database.ExpectationDatabase --+
                                           |
                                          PreviousTestRun

A 'PreviousTestRun' uses test results as expectations.

A 'PreviousTestRun' uses a ResultsFile such as generated by 'qmtest run' to determine the expected outcome for the current test run.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, **args)
Construct a new 'Extension'.
source code
 
Lookup(self, test_id)
Look up the expected outcome for the given test.
source code

Inherited from expectation_database.ExpectationDatabase: GetExpectedOutcomes

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  file_name = TextField(description= "The name of the results fi...
  results_file = PythonField("The results file.")

Inherited from expectation_database.ExpectationDatabase: kind, test_database, testrun_parameters

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

Lookup(self, test_id)

source code 

Look up the expected outcome for the given test.

'test_id' -- test-id for which the outcome is queried.

returns -- a Result object associated with this test_id.

Overrides: expectation_database.ExpectationDatabase.Lookup
(inherited documentation)

Class Variable Details [hide private]

file_name

Value:
TextField(description= "The name of the results file.")

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_result_reader.FileResultReader-class.html0000664000076400007640000005131011122067150032411 0ustar stefanstefan qm.test.file_result_reader.FileResultReader
Package qm :: Package test :: Module file_result_reader :: Class FileResultReader
[hide private]
[frames] | no frames]

Class FileResultReader

source code

            object --+        
                     |        
   extension.Extension --+    
                         |    
result_reader.ResultReader --+
                             |
                            FileResultReader
Known Subclasses:

A 'FileResultReader' gets its input from a file.

A 'FileResultReader' is an abstract base class for other result reader classes that read results from a single file. The file from which results should be read can be specified using either the 'filename' argument or the 'file' argument. The latter is for use by QMTest internally.

Nested Classes [hide private]
  InvalidFile
An 'InvalidFile' exception indicates an incorrect file format.

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'FileResultReader'.
source code

Inherited from result_reader.ResultReader: GetAnnotations, GetResult, __iter__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.fields.TextField'> filename>, <<class...
A list of the arguments to the extension class.
  _is_binary_file = 0
If true, results are stored in a binary format.
  _argument_dictionary = {'file': <<class 'qm.fields.PythonField...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.PythonField'> file>, <<cl...
A list of all the 'Field's in this class.
  file = None
  filename = ''

Inherited from result_reader.ResultReader: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'FileResultReader'.

'arguments' -- As for 'ResultReader'.

If the file provided is not in the input format expected by this result reader, the derived class '__init__' function must raise an 'InvalidStream' exception.

Overrides: object.__init__

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[<<class 'qm.fields.TextField'> filename>,
 <<class 'qm.fields.PythonField'> file>]

_is_binary_file

If true, results are stored in a binary format.

This flag can be overridden by derived classes.

Value:
0

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'file': <<class 'qm.fields.PythonField'> file>,
 'filename': <<class 'qm.fields.TextField'> filename>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.PythonField'> file>,
 <<class 'qm.fields.TextField'> filename>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_InSV-pysrc.html0000664000076400007640000054034511122067161030744 0ustar stefanstefan qm.external.DocumentTemplate.DT_InSV
Package qm :: Package external :: Package DocumentTemplate :: Module DT_InSV
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_InSV

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  __doc__='''Sequence variables support 
 14   
 15   
 16  $Id: DT_InSV.py 1069 2008-11-13 21:55:43Z stefan $''' 
 17  __version__='$Revision: 1069 $'[11:-2] 
 18   
 19  from string import lower, rfind, split, join 
 20  from math import sqrt 
 21  TupleType=type(()) 
 22  try: 
 23      import Missing 
 24      mv=Missing.Value 
 25  except: mv=None 
 26   
 27   
29
30 - def __init__(self,items=None,query_string='',start_name_re=None):
31 32 self.items=items 33 self.query_string=query_string 34 self.start_name_re=start_name_re 35 36 self.data=data={ 37 'previous-sequence': 0, 38 'next-sequence': 0, 39 'sequence-start': 1, 40 'sequence-end': 0, 41 }
42 43
44 - def __len__(self): return 1
45 - def number(self,index): return index+1
46 - def even(self,index): return index%2 == 0
47 - def odd(self,index): return index%2
48 - def letter(self,index): return chr(ord('a')+index)
49 - def Letter(self,index): return chr(ord('A')+index)
50 - def key(self,index): return self.items[index][0]
51 - def item(self,index, tt=type(())):
52 i=self.items[index] 53 if type(i) is tt and len(i)==2: return i[1] 54 return i
55
56 - def roman(self,index): return lower(self.Roman(index))
57
58 - def Roman(self,num):
59 # Force number to be an integer value 60 num = int(num)+1 61 62 # Initialize roman as an empty string 63 roman = '' 64 65 while num >= 1000: 66 num = num - 1000 67 roman = '%sM' % roman 68 69 while num >= 500: 70 num = num - 500 71 roman = '%sD' % roman 72 73 while num >= 100: 74 num = num - 100 75 roman = '%sC' % roman 76 77 while num >= 50: 78 num = num - 50 79 roman = '%sL' % roman 80 81 while num >= 10: 82 num = num - 10 83 roman = '%sX' % roman 84 85 while num >= 5: 86 num = num - 5 87 roman = '%sV' % roman 88 89 while num < 5 and num >= 1: 90 num = num - 1 91 roman = '%sI' % roman 92 93 # Replaces special cases in Roman Numerals 94 95 roman = sub('DCCCC', 'CM', roman) 96 roman = sub('CCCC', 'CD', roman) 97 roman = sub('LXXXX', 'XC', roman) 98 roman = sub('XXXX', 'XL', roman) 99 roman = sub('VIIII', 'IX', roman) 100 roman = sub('IIII', 'IV', roman) 101 102 return roman
103 104
105 - def value(self,index,name):
106 data=self.data 107 item=self.items[index] 108 if type(item)==TupleType and len(item)==2: 109 item=item[1] 110 if data['mapping']: return item[name] 111 return getattr(item,name)
112
113 - def first(self,name,key=''):
114 data=self.data 115 if data['sequence-start']: return 1 116 index=data['sequence-index'] 117 return self.value(index,name) != self.value(index-1,name)
118
119 - def last(self,name,key=''):
120 data=self.data 121 if data['sequence-end']: return 1 122 index=data['sequence-index'] 123 return self.value(index,name) != self.value(index+1,name)
124
125 - def length(self, ignored):
126 l=self.data['sequence-length']=len(self.items) 127 return l
128
129 - def query(self, *ignored):
130 131 if self.start_name_re is None: raise KeyError, 'sequence-query' 132 query_string=self.query_string 133 while query_string and query_string[:1] in '?&': 134 query_string=query_string[1:] 135 while query_string[-1:] == '&': 136 query_string=query_string[:-1] 137 if query_string: 138 query_string='&%s&' % query_string 139 re=self.start_name_re 140 l=re.search_group(query_string, (0,)) 141 if l: 142 v=l[1] 143 l=l[0] 144 query_string=(query_string[:l]+ 145 query_string[l+len(v)-1:]) 146 query_string='?'+query_string[1:] 147 else: query_string='?' 148 self.data['sequence-query']=query_string 149 return query_string
150 151 152 statistic_names=( 153 'total', 'count', 'min', 'max', 'median', 'mean', 154 'variance', 'variance-n','standard-deviation', 'standard-deviation-n', 155 ) 156
157 - def statistics(self,name,key):
158 items=self.items 159 data=self.data 160 mapping=data['mapping'] 161 count=sum=sumsq=0 162 min=max=None 163 scount=smin=smax=None 164 values=[] 165 svalues=[] 166 for item in items: 167 try: 168 if mapping: item=item[name] 169 else: item=getattr(item,name) 170 try: 171 if item is mv: 172 item = None 173 if type(item)==type(1): 174 s=item*long(item) 175 else: 176 s=item*item 177 sum=sum+item 178 sumsq=sumsq+s 179 values.append(item) 180 if min is None: 181 min=max=item 182 else: 183 if item < min: min=item 184 if item > max: max=item 185 except: 186 if item is not None and item is not mv: 187 if smin is None: smin=smax=item 188 else: 189 if item < smin: smin=item 190 if item > smax: smax=item 191 svalues.append(item) 192 except: pass 193 194 # Initialize all stats to empty strings: 195 for stat in self.statistic_names: data['%s-%s' % (stat,name)]='' 196 197 count=len(values) 198 try: # Numeric statistics 199 n=float(count) 200 mean=sum/n 201 sumsq=sumsq/n - mean*mean 202 data['mean-%s' % name]=mean 203 data['total-%s' % name]=sum 204 data['variance-n-%s' % name]=sumsq 205 data['standard-deviation-n-%s' % name]=sqrt(sumsq) 206 if count > 1: 207 sumsq=sumsq*n/(n-1) 208 data['variance-%s' % name]=sumsq 209 data['standard-deviation-%s' % name]=sqrt(sumsq) 210 else: 211 data['variance-%s' % name]='' 212 data['standard-deviation-%s' % name]='' 213 except: 214 if min is None: min,max,values=smin,smax,svalues 215 else: 216 if smin < min: min=smin 217 if smax > max: max=smax 218 values=values+svalues 219 count=len(values) 220 221 data['count-%s' % name]=count 222 # data['_values']=values 223 if min is not None: 224 data['min-%s' % name]=min 225 data['max-%s' % name]=max 226 values.sort() 227 if count==1: 228 data['median-%s' % name]=min 229 else: 230 n=count+1 231 if n/2*2==n: data['median-%s' % name]=values[n/2-1] 232 else: 233 n=n/2 234 try: data['median-%s' % name]=(values[n]+values[n-1])/2 235 except: 236 try: data['median-%s' % name]=( 237 "between %s and %s" % (values[n],values[n-1])) 238 except: pass 239 240 return data[key]
241
242 - def next_batches(self, suffix='batches',key=''):
243 if suffix != 'batches': raise KeyError, key 244 data=self.data 245 sequence=self.items 246 try: 247 if not data['next-sequence']: return () 248 sz=data['sequence-step-size'] 249 start=data['sequence-step-start'] 250 end=data['sequence-step-end'] 251 l=len(sequence) 252 orphan=data['sequence-step-orphan'] 253 overlap=data['sequence-step-overlap'] 254 except: AttributeError, 'next-batches' 255 r=[] 256 while end < l: 257 start,end,spam=opt(end+1-overlap,0,sz,orphan,sequence) 258 v=sequence_variables(self.items, 259 self.query_string,self.start_name_re) 260 d=v.data 261 d['batch-start-index']=start-1 262 d['batch-end-index']=end-1 263 d['batch-size']=end+1-start 264 d['mapping']=data['mapping'] 265 r.append(v) 266 data['next-batches']=r 267 return r
268
269 - def previous_batches(self, suffix='batches',key=''):
270 if suffix != 'batches': raise KeyError, key 271 data=self.data 272 sequence=self.items 273 try: 274 if not data['previous-sequence']: return () 275 sz=data['sequence-step-size'] 276 start=data['sequence-step-start'] 277 end=data['sequence-step-end'] 278 l=len(sequence) 279 orphan=data['sequence-step-orphan'] 280 overlap=data['sequence-step-overlap'] 281 except: AttributeError, 'previous-batches' 282 r=[] 283 while start > 1: 284 start,end,spam=opt(0,start-1+overlap,sz,orphan,sequence) 285 v=sequence_variables(self.items, 286 self.query_string,self.start_name_re) 287 d=v.data 288 d['batch-start-index']=start-1 289 d['batch-end-index']=end-1 290 d['batch-size']=end+1-start 291 d['mapping']=data['mapping'] 292 r.append(v) 293 r.reverse() 294 data['previous-batches']=r 295 return r
296 297 298 special_prefixes={ 299 'first': first, 300 'last': last, 301 'previous': previous_batches, 302 'next': next_batches, 303 # These two are for backward compatability with a missfeature: 304 'sequence-index': lambda self, suffix, key: self['sequence-'+suffix], 305 'sequence-index-is': lambda self, suffix, key: self['sequence-'+suffix], 306 } 307 for n in statistic_names: special_prefixes[n]=statistics 308
309 - def __getitem__(self,key, 310 special_prefixes=special_prefixes, 311 special_prefix=special_prefixes.has_key 312 ):
313 data=self.data 314 if data.has_key(key): return data[key] 315 316 l=rfind(key,'-') 317 if l < 0: raise KeyError, key 318 319 suffix=key[l+1:] 320 prefix=key[:l] 321 322 if hasattr(self, suffix): 323 try: v=data[prefix+'-index'] 324 except: pass 325 else: return getattr(self,suffix)(v) 326 327 if special_prefix(prefix): 328 return special_prefixes[prefix](self, suffix, key) 329 330 if prefix[-4:]=='-var': 331 prefix=prefix[:-4] 332 try: return self.value(data[prefix+'-index'],suffix) 333 except: pass 334 335 if key=='sequence-query': return self.query() 336 337 raise KeyError, key
338 339 340 341
342 -def sub(s1, s2, src):
343 return join(split(src, s1), s2)
344
345 -def opt(start,end,size,orphan,sequence):
346 if size < 1: 347 if start > 0 and end > 0 and end >= start: 348 size=end+1-start 349 else: size=7 350 351 if start > 0: 352 353 try: sequence[start-1] 354 except: start=len(sequence) 355 # if start > l: start=l 356 357 if end > 0: 358 if end < start: end=start 359 else: 360 end=start+size-1 361 try: sequence[end+orphan-1] 362 except: end=len(sequence) 363 # if l - end < orphan: end=l 364 elif end > 0: 365 try: sequence[end-1] 366 except: end=len(sequence) 367 # if end > l: end=l 368 start=end+1-size 369 if start - 1 < orphan: start=1 370 else: 371 start=1 372 end=start+size-1 373 try: sequence[end+orphan-1] 374 except: end=len(sequence) 375 # if l - end < orphan: end=l 376 return start,end,size
377

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.dir_run_database-module.html0000664000076400007640000000216211122067144031243 0ustar stefanstefan dir_run_database

Module dir_run_database


Classes

DirRunDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.setup-module.html0000664000076400007640000000170311122067144031575 0ustar stefanstefan setup

Module setup



[hide private] ././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.sql_result_stream.SQLResultStream-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.sql_result_stream.SQLResultStream-class.ht0000664000076400007640000006240111122067147033247 0ustar stefanstefan qm.test.classes.sql_result_stream.SQLResultStream
Package qm :: Package test :: Package classes :: Module sql_result_stream :: Class SQLResultStream
[hide private]
[frames] | no frames]

Class SQLResultStream

source code

            object --+        
                     |        
   extension.Extension --+    
                         |    
result_stream.ResultStream --+
                             |
            object --+       |
                     |       |
   extension.Extension --+   |
                         |   |
             _SQLConnected --+
                             |
                            SQLResultStream

A 'SQLResultStream' writes results out to an SQL database.

This class currently supports PostgreSQL only.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code
 
WriteAnnotation(self, key, value)
Output an annotation for this run.
source code
 
WriteResult(self, result)
Output a test result.
source code
 
Summarize(self)
Output summary information about the results.
source code

Inherited from result_stream.ResultStream: WriteAllAnnotations

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  _argument_dictionary = {'connection': <<class 'qm.fields.Pytho...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.TextField'> db_module>, <...
A list of all the 'Field's in this class.

Inherited from result_stream.ResultStream: expected_outcomes, kind

Inherited from _SQLConnected: arguments, connection, db_module, db_name

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

WriteAnnotation(self, key, value)

source code 

Output an annotation for this run.

Subclasses should override this if they want to store/display annotations; the default implementation simply discards them.

'key' -- the key value as a string.

'value' -- the value of this annotation as a string.

Overrides: result_stream.ResultStream.WriteAnnotation
(inherited documentation)

WriteResult(self, result)

source code 

Output a test result.

Subclasses must override this method; the default implementation raises a 'NotImplementedError'.

'result' -- A 'Result'.

Overrides: result_stream.ResultStream.WriteResult
(inherited documentation)

Summarize(self)

source code 

Output summary information about the results.

When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point.

Derived class methods may override this method. They should, however, invoke this version before returning.

Overrides: result_stream.ResultStream.Summarize
(inherited documentation)

Class Variable Details [hide private]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'connection': <<class 'qm.fields.PythonField'> connection>,
 'db_module': <<class 'qm.fields.TextField'> db_module>,
 'db_name': <<class 'qm.fields.TextField'> db_name>,
 'expected_outcomes': <<class 'qm.fields.PythonField'> expected_outcom\
es>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.TextField'> db_module>,
 <<class 'qm.fields.PythonField'> expected_outcomes>,
 <<class 'qm.fields.PythonField'> connection>,
 <<class 'qm.fields.TextField'> db_name>]

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.target-module.html0000664000076400007640000000207411122067144025611 0ustar stefanstefan target

Module target


Classes

Target

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command-module.html0000664000076400007640000001116311122067145025142 0ustar stefanstefan qm.dist.command
Package qm :: Package dist :: Package command
[hide private]
[frames] | no frames]

Package command

source code

Submodules [hide private]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.LoadContextPage-class.html0000664000076400007640000003547311122067151027740 0ustar stefanstefan qm.test.web.web.LoadContextPage
Package qm :: Package test :: Package web :: Module web :: Class LoadContextPage
[hide private]
[frames] | no frames]

Class LoadContextPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      LoadContextPage

DTML page for uploading a context.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server)
Construct a new 'LoadContextPage'.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]
  title = "Load Context"
The title for the page.
  heading = "Load the context from a file."
The heading printed across the top of the page.
  prompt = "The file from which to load the context."
The prompt for the file name.
  submit_url = "submit-context-file"
The URL to which the file should be submitted.

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server)
(Constructor)

source code 

Construct a new 'LoadContextPage'.

'server' -- The 'QMTestServer' creating this page.

Overrides: web.DtmlPage.__init__

././@LongLink0000000000000000000000000000016000000000000011562 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database.ParameterDatabase.ImplicitSuite-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database.ParameterDatabase.ImplicitSuite0000664000076400007640000004106111122067150033241 0ustar stefanstefan qm.test.parameter_database.ParameterDatabase.ImplicitSuite
Package qm :: Package test :: Module parameter_database :: Class ParameterDatabase :: Class ImplicitSuite
[hide private]
[frames] | no frames]

Class ImplicitSuite

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
            suite.Suite --+
                          |
                         ParameterDatabase.ImplicitSuite

ImplicitSuite represents a suite obtained from a test and a set of parameters applied to it.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, db, suite_id)
Construct a new 'Runnable'.
source code
 
GetTestIds(self)
Return the tests contained in this suite.
source code
 
IsImplicit(self)
Return true if this is an implicit test suite.
source code

Inherited from suite.Suite: GetAllTestAndSuiteIds, GetDatabase, GetId, GetSuiteIds

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from suite.Suite: EXTRA_DATABASE, EXTRA_ID, arguments, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, db, suite_id)
(Constructor)

source code 

Construct a new 'Runnable'.

'arguments' -- As for 'Extension.__init__'.

'args' -- As for 'Extension.__init__'.

Overrides: object.__init__
(inherited documentation)

GetTestIds(self)

source code 

Return the tests contained in this suite.

returns -- A sequence of labels corresponding to the tests contained in this suite. Tests that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetTestIds
(inherited documentation)

IsImplicit(self)

source code 

Return true if this is an implicit test suite.

Implicit test suites cannot be edited.

Overrides: suite.Suite.IsImplicit
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.report-module.html0000664000076400007640000001113011122067145025045 0ustar stefanstefan qm.test.report
Package qm :: Package test :: Module report
[hide private]
[frames] | no frames]

Module report

source code

Classes [hide private]
  ReportGenerator
A 'ReportGenerator' generates a test report from one or more result files.
qmtest-2.4.1/share/doc/qmtest/html/manual/class-tree.html0000664000076400007640000013016311122067144022726 0ustar stefanstefan Class Hierarchy
 
[hide private]
[frames] | no frames]
[ Module Hierarchy | Class Hierarchy ]

Class Hierarchy

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_result_stream.FileResultStream-class.html0000664000076400007640000005350111122067150032477 0ustar stefanstefan qm.test.file_result_stream.FileResultStream
Package qm :: Package test :: Module file_result_stream :: Class FileResultStream
[hide private]
[frames] | no frames]

Class FileResultStream

source code

            object --+        
                     |        
   extension.Extension --+    
                         |    
result_stream.ResultStream --+
                             |
                            FileResultStream
Known Subclasses:

A 'FileResultStream' writes its output to a file.

A 'FileResultStream' is an abstract base class for other result stream classes that store results in a single file. The file to which results should be written can be specified using either the 'filename' argument or the 'file' argument. The latter is for use by QMTest internally.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code

Inherited from result_stream.ResultStream: Summarize, WriteAllAnnotations, WriteAnnotation, WriteResult

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.fields.TextField'> filename>, <<class...
A list of the arguments to the extension class.
  _is_binary_file = 0
If true, the file written is a binary file.
  _argument_dictionary = {'expected_outcomes': <<class 'qm.field...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.PythonField'> expected_ou...
A list of all the 'Field's in this class.
  file = None
  filename = ''

Inherited from result_stream.ResultStream: expected_outcomes, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[<<class 'qm.fields.TextField'> filename>,
 <<class 'qm.fields.PythonField'> file>]

_is_binary_file

If true, the file written is a binary file.

This flag can be overridden by derived classes.

Value:
0

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'expected_outcomes': <<class 'qm.fields.PythonField'> expected_outcom\
es>,
 'file': <<class 'qm.fields.PythonField'> file>,
 'filename': <<class 'qm.fields.TextField'> filename>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.PythonField'> expected_outcomes>,
 <<class 'qm.fields.PythonField'> file>,
 <<class 'qm.fields.TextField'> filename>]

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-_.html0000664000076400007640000052727411122067144024344 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

_



qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.ssh_host-module.html0000664000076400007640000000226011122067144027606 0ustar stefanstefan ssh_host

Module ssh_host


Classes

RSHHost
SSHHost

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-A.html0000664000076400007640000004466511122067144024304 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

A



././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_engine.ExecutionEngine.__TestStatus-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_engine.ExecutionEngine.__TestStatus-clas0000664000076400007640000005014711122067150033273 0ustar stefanstefan qm.test.execution_engine.ExecutionEngine.__TestStatus
Package qm :: Package test :: Module execution_engine :: Class ExecutionEngine :: Class __TestStatus
[hide private]
[frames] | no frames]

Class __TestStatus

source code

object --+
         |
        ExecutionEngine.__TestStatus

A '__TestStatus' indicates whether or not a test has been run.

The 'outcome' slot indicates whether the test has not be queued so
that it can be run, has completed, or has not been processed at all.

If there are tests that have this test as a prerequisite, they are
recorded in the 'dependants' slot.

Ever test passes through the following states, in the following
order:

1. Initial

   A test in this state has not yet been processed.  In this state,
   the 'outcome' slot is 'None'.

2. Queued

   A test in this state has been placed on the stack of tests
   waiting to run.  In this state, the 'outcome' slot is
   'QUEUED'.  Such a test may be waiting for prerequisites to
   complete before it can run.

3. Ready

   A test in this state is ready to run.  All prerequisites have
   completed, and their outcomes were as expected.  In this
   state, the 'outcome' slot is 'READY'.

4. Finished

   A test in this state has finished running.  In this state, the
   'outcome' slot is one of the 'Result.outcomes'.

The only exception to this order is that when an error is noted
(like a failure to load a test from the database, or a
prerequisite has an unexpected outcome) a test may jump to the
"finished" state without passing through intermediate states.

Instance Methods [hide private]
 
__init__(self)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code
 
GetState(self)
Return the state of this test.
source code
 
NoteQueued(self)
Place the test into the "queued" state.
source code
 
HasBeenQueued(self)
Returns true if the test was ever queued.
source code
 
NoteReady(self)
Place the test into the "ready" state.
source code
 
HasBeenReady(self)
Returns true if the test was ever ready.
source code
 
IsFinished(self)
Returns true if the test is in the "finished" state.
source code
 
NoteDependant(self, test_id)
Note that 'test_id' depends on 'self'.
source code

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  QUEUED = "QUEUED"
  READY = "READY"
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Overrides: object.__init__
(inherited documentation)

GetState(self)

source code 

Return the state of this test.

returns -- The state of this test, using the representation documented above.

HasBeenQueued(self)

source code 

Returns true if the test was ever queued.

returns -- True if the test has ever been on the queue. Such a test may be ready to run, or may in fact have already run to completion.

HasBeenReady(self)

source code 

Returns true if the test was ever ready.

returns -- True if the test was every ready to run. Such a test may have already run to completion.

IsFinished(self)

source code 

Returns true if the test is in the "finished" state.

returns -- True if this test is in the "finished" state.

NoteDependant(self, test_id)

source code 

Note that 'test_id' depends on 'self'.

'test_id' -- The name of a test. That test has this test as a prerequisite.


././@LongLink0000000000000000000000000000015700000000000011570 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database.ParameterDatabase.WrapperSuite-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database.ParameterDatabase.WrapperSuite-0000664000076400007640000005104411122067150033166 0ustar stefanstefan qm.test.parameter_database.ParameterDatabase.WrapperSuite
Package qm :: Package test :: Module parameter_database :: Class ParameterDatabase :: Class WrapperSuite
[hide private]
[frames] | no frames]

Class WrapperSuite

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
            suite.Suite --+
                          |
                         ParameterDatabase.WrapperSuite

As tests from the wrapped Database are mapped to suites, suites from the wrapped Database have to be recreated with all tests replaced by ImplicitSuite instances. Additionally, new (explicit) suites may be added.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, db, suite, suite_ids=None)
Take over suite_ids from the wrapped database but replace test_ids by suite_ids if there are parameters available for them.
source code
 
GetSuiteIds(self)
Return the suites contained in this suite.
source code
 
GetTestIds(self)
Return the tests contained in this suite.
source code
 
IsImplicit(self)
Return true if this is an implicit test suite.
source code
 
GetAllTestAndSuiteIds(self)
Return the tests/suites contained in this suite and its subsuites.
source code

Inherited from suite.Suite: GetDatabase, GetId

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from suite.Suite: EXTRA_DATABASE, EXTRA_ID, arguments, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, db, suite, suite_ids=None)
(Constructor)

source code 

Take over suite_ids from the wrapped database but replace test_ids by suite_ids if there are parameters available for them.

Overrides: object.__init__

GetSuiteIds(self)

source code 

Return the suites contained in this suite.

returns -- A sequence of labels corresponding to the suites contained in this suite. Suites that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetSuiteIds
(inherited documentation)

GetTestIds(self)

source code 

Return the tests contained in this suite.

returns -- A sequence of labels corresponding to the tests contained in this suite. Tests that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetTestIds
(inherited documentation)

IsImplicit(self)

source code 

Return true if this is an implicit test suite.

Implicit test suites cannot be edited.

Overrides: suite.Suite.IsImplicit
(inherited documentation)

GetAllTestAndSuiteIds(self)

source code 

Return the tests/suites contained in this suite and its subsuites.

returns -- A pair '(test_ids, suite_ids)'. The 'test_ids' and 'suite_ids' elements are both sequences of labels. The values returned include all tests and suites that are contained in this suite and its subsuites, recursively.

Overrides: suite.Suite.GetAllTestAndSuiteIds
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DTtestExpr-module.html0000664000076400007640000000310311122067144032477 0ustar stefanstefan DTtestExpr

Module DTtestExpr


Functions

test1
test2
test3
test4

Variables

__doc__

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform_win32.SignalException-class.html0000664000076400007640000002142611122067146030347 0ustar stefanstefan qm.platform_win32.SignalException
Package qm :: Module platform_win32 :: Class SignalException
[hide private]
[frames] | no frames]

Class SignalException

source code

              object --+        
                       |        
exceptions.BaseException --+    
                           |    
        exceptions.Exception --+
                               |
                              SignalException

Instance Methods [hide private]
 
__init__(self, *args)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, *args)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Overrides: object.__init__
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.serial_target.SerialTarget-class.html0000664000076400007640000004013511122067147032231 0ustar stefanstefan qm.test.classes.serial_target.SerialTarget
Package qm :: Package test :: Package classes :: Module serial_target :: Class SerialTarget
[hide private]
[frames] | no frames]

Class SerialTarget

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
          target.Target --+
                          |
                         SerialTarget

A target that runs tests in serial on the local machine.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, properties)
Construct a 'Target'.
source code
 
IsIdle(self)
Return true if the target is idle.
source code
 
_GetTemporaryDirectory(self)
Return the path to a temporary directory.
source code

Inherited from target.Target: GetDatabase, GetGroup, GetName, IsInGroup, RunTest, Start, Stop

Inherited from target.Target (private): _BeginResourceSetUp, _CleanUpResource, _FinishResourceSetUp, _RecordResult, _SetUpResource

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from target.Target: arguments, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, properties)
(Constructor)

source code 

Construct a 'Target'.

'database' -- The 'Database' containing the tests that will be run.

'arguments' -- As for 'Extension.__init__'.

'args' -- As for 'Extension.__init__'.

Overrides: object.__init__
(inherited documentation)

IsIdle(self)

source code 

Return true if the target is idle.

returns -- True if the target is idle. If the target is idle, additional tasks may be assigned to it.

Overrides: target.Target.IsIdle

_GetTemporaryDirectory(self)

source code 

Return the path to a temporary directory.

returns -- The path to a temporary directory to pass along to tests and resources via the 'TMPDIR_CONTEXT_PROPERTY'.

Overrides: target.Target._GetTemporaryDirectory
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.cmdline-pysrc.html0000664000076400007640000033551011122067152024053 0ustar stefanstefan qm.cmdline
Package qm :: Module cmdline
[hide private]
[frames] | no frames]

Source Code for Module qm.cmdline

  1  ######################################################################## 
  2  # 
  3  # File:   cmdline.py 
  4  # Author: Benjamin Chelf 
  5  # Date:   2001-01-09 
  6  # 
  7  # Contents: 
  8  #   Code for command line interface. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  #  Using the Command Parser 
 18  # 
 19  #  The command parser can be used by giving a list of options and 
 20  #  commands to be parsed. See the constructor below for the exact 
 21  #  structure of those things. You can then use the parser to 1) generate 
 22  #  help strings for the general program, 2) generate help strings for 
 23  #  specific commands, and 3) parse command lines to split up which 
 24  #  options were passed, which command was given, and the arguments and 
 25  #  options to that command that were specified. 
 26  # 
 27  ######################################################################## 
 28   
 29  ######################################################################## 
 30  # imports 
 31  ######################################################################## 
 32   
 33  import copy 
 34  import getopt 
 35  import qm 
 36  import string 
 37  import structured_text 
 38  import sys 
 39   
 40  ######################################################################## 
 41  # classes 
 42  ######################################################################## 
 43   
44 -class CommandError(qm.UserError):
45 46 pass
47 48 49
50 -class CommandParser:
51 """Class for the functionality that parses the command line. 52 53 The command parser is used to easily specify a list of command line 54 options and commands to be parsed from an argument list.""" 55
56 - def __init__(self, name, options, commands, conflicting_options=()):
57 """Create a new command parser. 58 59 'name' -- The name of the executable that we are currently 60 using. This will normally be argv[0]. 61 62 'options' -- A list of 4-tuples specifying options that you wish 63 this parser to accept. The 4-tuple has the following form: 64 (short_form, long_form, options, description). 'short_form' 65 must be exactly one character. 'long_form' must be specified 66 for every option in the list. 'arg_name' is a string 67 representing the name of the argument that is passed to this 68 option. If it is 'None,' then this option doesn't take an 69 argument. 'description' is a string describing the option. 70 71 'commands' -- A list of 5-tuples specifying commands to be 72 accepted after the command line options. The 5-tuple has the 73 form '(name, short_description, args_string, long_description, 74 options)'. 75 76 'name' -- The string for the command. 77 78 'short_description' -- A short description of the command to 79 be printed out in general help. 80 81 'args_string' -- The string that will be printed after the 82 command in the command specific help. 83 84 'long_description' -- The long description to be printed out 85 in the command specfic help. 86 87 'options' -- A list of 4-tuples of the same form as the 88 'options' described above. 89 90 'conflicting_options' -- A sequence of sets of conflicting 91 options. Each element is a sequence of option specifiers in the 92 same form as 'options', above.""" 93 94 self.__name = name 95 96 # Check that the options are ok. 97 self.CheckOptions(options) 98 self.__options = copy.deepcopy(options) 99 100 self.__option_to_long = {} 101 for option in self.__options: 102 if option[0]: 103 # Check for duplicate short options. 104 assert not self.__option_to_long.has_key('-' + option[0]) 105 self.__option_to_long['-' + option[0]] = option[1] 106 # Check for duplicate long options. 107 assert not self.__option_to_long.has_key('--' + option[1]) 108 self.__option_to_long['--' + option[1]] = option[1] 109 110 # Check that the options for each command are ok. 111 for command in commands: 112 self.CheckOptions(command[4]) 113 114 self.__commands = copy.deepcopy(commands) 115 for i in range(0, len(self.__commands)): 116 command = self.__commands[i] 117 map = {} 118 for option in command[4]: 119 if option[0] is not None: 120 # Check for duplicate short options. 121 if map.has_key('-' + option[0]): 122 raise ValueError, \ 123 "duplicate short command option -%s" \ 124 % option[0] 125 map['-' + option[0]] = option[1] 126 # Check for duplicate long options. 127 if map.has_key('--' + option[1]): 128 raise ValueError, \ 129 "duplicate long command option --%s" % option[1] 130 map['--' + option[1]] = option[1] 131 command = command + (map,) 132 self.__commands[i] = command 133 134 # Build the options string for getopt. 135 self.__getopt_options = self.BuildGetoptString(self.__options) 136 137 # Check that all options in the conflicting options set are 138 # included somewhere. 139 for conflict_set in conflicting_options: 140 # Check each option in each set. 141 for option_spec in conflict_set: 142 found = 0 143 # Check in the global options. 144 if option_spec in options: 145 found = 1 146 break 147 if not found: 148 # Check in the command options for each command. 149 for command in commands: 150 if option in command[4]: 151 found = 1 152 break 153 if not found: 154 # This option spec wasn't found anywhere. 155 raise ValueError, \ 156 "unknown option --%s in conflict set", option[1] 157 # Store for later. 158 self.__conflicting_options = conflicting_options
159 160
161 - def CheckOptions(self, options):
162 """Check that a list of options 4-tuples is correct. 163 164 'options' -- A list of 4-tuples as described above. 165 166 returns -- 1 if the options are all valid, 0 otherwise.""" 167 168 for short_option, long_option, options, descripton in options: 169 # The short form of the option must have exactly 1 character. 170 if short_option != None and len(short_option) != 1: 171 raise ValueError, "short option must have exactly 1 character" 172 # The long form of the option must be specified. 173 if long_option == None or len(long_option) == 0: 174 raise ValueError, \ 175 "long option must be specified for -%s" % short_option 176 177 return 1
178 179
180 - def BuildGetoptList(self, options):
181 """Build a getopt list for the long options. 182 183 'options' -- A list of 4-tuples as described above. 184 185 returns -- A list to be passed to getopt to parse long options.""" 186 187 # Build the options string for getopt. 188 getopt_list = [] 189 190 for option in options: 191 # Tell getopt that this option takes an argument. 192 if option[2] != None: 193 getopt_list.append(option[1] + '=') 194 else: 195 getopt_list.append(option[1]) 196 197 return getopt_list
198 199
200 - def BuildGetoptString(self, options):
201 """Build a getopt string for the options passed in. 202 203 'options' -- A list of 4-tuples as described above. 204 205 returns -- A string to be passed to getopt to parse the 206 options.""" 207 208 # Build the options string for getopt. 209 getopt_string = '' 210 211 for option in options: 212 if option[0] is not None: 213 getopt_string = getopt_string + option[0] 214 # Tell getopt that this option takes an argument. 215 if option[2] != None: 216 getopt_string = getopt_string + ':' 217 218 return getopt_string
219 220
221 - def GetOptionsHelp(self, options):
222 """Return a string that is the basic help for options. 223 224 options -- A list of options to get the help string for. 225 226 returns -- A string to be printed for the options.""" 227 228 help_string = "" 229 230 # Print out the short form, long form, and then the description. 231 for option in options: 232 # Format the short form, if there is one. 233 if option[0] is None: 234 short_form = " " 235 else: 236 short_form = "-%s," % option[0] 237 # Format the long form. Include the option arugment, if 238 # there is one. 239 if option[2] is None: 240 long_form = "--%-24s" % option[1] 241 else: 242 long_form = "--%-24s" % (option[1] + " " + option[2]) 243 # Generate a line for this option. 244 help_string = help_string \ 245 + " %s %s: %s\n" \ 246 % (short_form, long_form, option[3]) 247 248 return help_string
249 250
251 - def GetBasicHelp(self):
252 """Return a string that is the basic help for the commands. 253 254 returns -- A string to be printed with basic functionality of 255 arguments and commands.""" 256 257 help_string = "Usage: %s " % self.__name 258 help_string = help_string + "[ OPTION... ] COMMAND " \ 259 "[ COMMAND-OPTION... ] [ ARGUMENT... ]\n\n" 260 help_string = help_string + "Options:\n" 261 help_string = help_string + self.GetOptionsHelp(self.__options) 262 help_string = help_string + "\nCommands:\n" 263 # Print out the commands and their short descriptions. 264 for command in self.__commands: 265 help_add = "%-30s: %s"%(command[0], command[1]) 266 help_string = help_string + " %s\n"%(help_add) 267 help_string = help_string \ 268 + "\nInvoke\n %s COMMAND --help\n" \ 269 "for information about " \ 270 "COMMAND-OPTIONS and ARGUMENTS.\n\n" % self.__name 271 272 return help_string
273 274
275 - def GetCommandHelp(self, command):
276 """Return a string that is the help for a specific command. 277 278 command -- A string of the command that you want help for. 279 280 returns -- A string of help for a given command.""" 281 282 help_string = "Usage: %s %s [ OPTIONS ] "%(self.__name, command) 283 for command_item in self.__commands: 284 if command_item[0] == command: 285 help_string = help_string + command_item[2] + "\n\n" 286 help_string = help_string + "Options:\n" 287 help_string = help_string \ 288 + self.GetOptionsHelp(command_item[4]) 289 help_string = help_string + "\n" 290 help_string = help_string \ 291 + structured_text.to_text(command_item[3]) 292 return help_string 293 294 return "Command not found"
295 296
297 - def ParseCommandLine(self, argv):
298 """Parse a command line. 299 300 'argv' -- A string containing the command line starting with 301 argv[1]. It should not contain the name of the executed program. 302 303 returns -- A 4-tuple of the options given, the command given, 304 the command options, and the command arguments. Its form is 305 this: (options, command, command_options, command_args). 306 'options' is a list of 2-tuples indicating each option specified 307 and the argument given to that option (if applicable). 308 'command' is the command given. 'command_options' is a list of 309 2-tuples indicating each option given to the command and its 310 possible argument. 'command_args' is a list of arguments as 311 given to the command. If no command is given, then the function 312 will return '' for the command, [] for the arguments, and [] for 313 the command options. 314 315 raises -- 'CommandError' if the command is invalid.""" 316 317 # Get the options off of the front of the command line. 318 getopt_list = self.BuildGetoptList(self.__options) 319 320 try: 321 options, args = getopt.getopt(argv, self.__getopt_options, 322 getopt_list) 323 except getopt.error, msg: 324 raise CommandError, msg 325 326 for i in range(0, len(options)): 327 option = options[i] 328 new_option = (self.__option_to_long[option[0]], option[1]) 329 options[i] = new_option 330 331 # Did not specify anything on the command line except options. 332 if args == []: 333 return (options, '', [], []) 334 335 # Get the command. 336 command = args[0] 337 338 # This checks to make sure the command they specified is actually 339 # a command that we know. Checking this now saves trouble 340 # in having to do it later. 341 found = 0 342 for command_item in self.__commands: 343 if command == command_item[0]: 344 found = 1 345 346 if found == 0: 347 # The command they specified does not exist; print out the 348 # help and raise an exception. 349 raise CommandError, \ 350 qm.error("unrecognized command", command=command) 351 352 # Get the arguments to the command. 353 command_options = [] 354 355 for command_item in self.__commands: 356 if command_item[0] == command: 357 command_options = command_item[4] 358 break 359 getopt_string = self.BuildGetoptString(command_options) 360 getopt_list = self.BuildGetoptList(command_options) 361 try: 362 command_options, command_args = getopt.getopt(args[1:], 363 getopt_string, 364 getopt_list) 365 except getopt.error, msg: 366 raise CommandError, "%s: %s" % (command, msg) 367 368 for i in range(0, len(command_options)): 369 option = command_options[i] 370 new_option = (command_item[5][option[0]], option[1]) 371 command_options[i] = new_option 372 373 # Check for mutually exclusive options. First generate a set of 374 # all the options that were specified, both global options and 375 # command options. 376 all_options = map(lambda option: option[0], 377 options + command_options) 378 # Loop over sets of conflicting options. 379 for conflict_set in self.__conflicting_options: 380 # Generate sequence of names of the conflicting options. 381 conflict_names = map(lambda opt_spec: opt_spec[1], conflict_set) 382 # Filter out options that were specified that aren't in the 383 # set of conflicting options. 384 conflict_filter = lambda option, conflict_names=conflict_names: \ 385 option in conflict_names and option 386 matches = filter(conflict_filter, all_options) 387 # Was more than one option from the conflicting set specified? 388 if len(matches) > 1: 389 # Yes; that's a user error. 390 raise qm.cmdline.CommandError, \ 391 qm.error("conflicting options", 392 option1=matches[0], 393 option2=matches[1]) 394 395 return (options, command, command_options, command_args)
396

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.lock-module.html0000664000076400007640000000675311122067145023523 0ustar stefanstefan qm.lock
Package qm :: Module lock
[hide private]
[frames] | no frames]

Module lock

source code

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-math-module.html0000664000076400007640000000575611122067144023674 0ustar stefanstefan math

Module math


Functions

acos
asin
atan
atan2
ceil
cos
cosh
degrees
exp
fabs
floor
fmod
frexp
hypot
ldexp
log
log10
modf
pow
radians
sin
sinh
sqrt
tan
tanh

Variables

e
pi

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.resource-module.html0000664000076400007640000001110011122067145025356 0ustar stefanstefan qm.test.resource
Package qm :: Package test :: Module resource
[hide private]
[frames] | no frames]

Module resource

source code

Classes [hide private]
  Resource
A 'Resource' sets up before a test and cleans up afterwards.
qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-W.html0000664000076400007640000003336411122067144024324 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

W



qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.suite-module.html0000664000076400007640000000206711122067144025456 0ustar stefanstefan suite

Module suite


Classes

Suite

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.directory_suite.DirectorySuite-class.html0000664000076400007640000004374711122067150031563 0ustar stefanstefan qm.test.directory_suite.DirectorySuite
Package qm :: Package test :: Module directory_suite :: Class DirectorySuite
[hide private]
[frames] | no frames]

Class DirectorySuite

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
            suite.Suite --+
                          |
                         DirectorySuite

A 'DirectorySuite' is a suite corresponding to a directory.

A 'DirectorySuite' is an implicit suite that contains all tests within a given directory. The directory is given by a label, not a file system directory, so a 'DirectorySuite' can work with any database.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, directory)
Construct a new 'DirectorySuite'.
source code
 
GetTestIds(self)
Return the tests contained in this suite.
source code
 
GetSuiteIds(self)
Return the suites contained in this suite.
source code
 
IsImplicit(self)
Return true if this is an implicit test suite.
source code

Inherited from suite.Suite: GetAllTestAndSuiteIds, GetDatabase, GetId

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from suite.Suite: EXTRA_DATABASE, EXTRA_ID, arguments, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, directory)
(Constructor)

source code 

Construct a new 'DirectorySuite'.

'database' -- The 'Database' instance containing this suite.

'directory' -- A label giving the directory corresponding to this suite.

Overrides: object.__init__

GetTestIds(self)

source code 

Return the tests contained in this suite.

returns -- A sequence of labels corresponding to the tests contained in this suite. Tests that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetTestIds

GetSuiteIds(self)

source code 

Return the suites contained in this suite.

returns -- A sequence of labels corresponding to the suites contained in this suite. Suites that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetSuiteIds

IsImplicit(self)

source code 

Return true if this is an implicit test suite.

Implicit test suites cannot be edited.

Overrides: suite.Suite.IsImplicit
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.VSEval-module.html0000664000076400007640000003415711122067145031024 0ustar stefanstefan qm.external.DocumentTemplate.VSEval
Package qm :: Package external :: Package DocumentTemplate :: Module VSEval
[hide private]
[frames] | no frames]

Module VSEval

source code

Very Safe Python Expressions


Version: 1069

Classes [hide private]
  Eval
Provide a very-safe environment for evaluating expressions
Functions [hide private]
 
default_slicer(env, s, *ind) source code
 
careful_mul(env, *factors) source code
Variables [hide private]
  __rcs_id__ = '$Id: VSEval.py 1069 2008-11-13 21:55:43Z stefan $'
  gparse = None
  nltosp = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t \x0b\x0c \x0e...
  default_globals = {'__builtins__': {}, '__guarded_getattr__': ...
  compiled_getattr = <code object <module> at 0x7f00bc584a08, fi...
Variables Details [hide private]

nltosp

Value:
'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t \x0b\x0c \x0e\x0f\x10\x11\x12\\
x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01\
23456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuv\
wxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x\
8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\
\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\x\
b1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\
\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\x\
...

default_globals

Value:
default_globals

compiled_getattr

Value:
<code object <module> at 0x7f00bc584a08, file "<string>", line 1>

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web-pysrc.html0000664000076400007640000430315711122067156024761 0ustar stefanstefan qm.test.web.web
Package qm :: Package test :: Package web :: Module web
[hide private]
[frames] | no frames]

Source Code for Module qm.test.web.web

   1  ######################################################################## 
   2  # 
   3  # File:   web.py 
   4  # Author: Alex Samuel 
   5  # Date:   2001-04-09 
   6  # 
   7  # Contents: 
   8  #   Common code for QMTest web user interface. 
   9  # 
  10  # Copyright (c) 2001 - 2005 by CodeSourcery, LLC.  All rights reserved.  
  11  # 
  12  # For license terms see the file COPYING. 
  13  # 
  14  ######################################################################## 
  15   
  16  ######################################################################## 
  17  # imports 
  18  ######################################################################## 
  19   
  20  import os 
  21  import qm 
  22  import qm.attachment 
  23  import qm.common 
  24  from   qm.extension import * 
  25  import qm.fields 
  26  import qm.label 
  27  import qm.test.base 
  28  import qm.test.cmdline 
  29  from   qm.test.context import * 
  30  from   qm.test.database import * 
  31  from   qm.test.classes.previous_testrun import PreviousTestRun 
  32  from   qm.test.execution_thread import * 
  33  from   qm.test.result import * 
  34  from   qm.test.result_stream import * 
  35  from   qm.test.suite import * 
  36  import qm.web 
  37  import string 
  38  import StringIO 
  39  import sys 
  40  import time 
  41   
  42  ######################################################################## 
  43  # classes 
  44  ######################################################################## 
  45   
46 -class Item:
47 """An 'Item' provides a convenient way to pass around named values. 48 It is iterated over in listings generated by various dtml templates.""" 49
50 - def __init__(self, id, **kwds):
51 """Construct a new 'Item'. 52 53 'id' -- The identifier. 54 55 'kwds' -- A dictionary of named values to store.""" 56 57 self.id = id 58 self.__dict__.update(kwds)
59 60 61
62 -class DefaultDtmlPage(qm.web.DtmlPage):
63 """Subclass of DTML page class for QMTest pages.""" 64 65 html_generator = "QMTest" 66 67 NEGATIVE_UNEXPECTED = Result.FAIL 68 """A test's result was unfavorably unexpected.""" 69 70 POSITIVE_UNEXPECTED = Result.PASS 71 """A test's result was favorably unexpected.""" 72 73 EXPECTED = "EXPECTED" 74 """A test's result was as expected.""" 75 76 EXPECTATION_KINDS \ 77 = [ NEGATIVE_UNEXPECTED, EXPECTED, POSITIVE_UNEXPECTED ] 78 """The kinds of expectations.""" 79 80 outcomes = Result.outcomes + [EXPECTED] 81
82 - def __init__(self, dtml_template, server, **attributes):
83 """Construct a new 'QMTestPage'. 84 85 'server' -- The 'QMTestServer' creating this page. 86 87 'dtml_template' -- The file name of the DTML template, relative 88 to the DTML directory.""" 89 90 self.server = server 91 92 # Set up the menus first; the attributes might override them. 93 if not server.GetRunDatabase(): 94 if server.GetDatabase().IsModifiable(): 95 self.file_menu_items = [ 96 ('New Test', "new-test"), 97 ('New Suite', "new-suite"), 98 ('New Resource', "new-resource"), 99 ] 100 else: 101 self.file_menu_items = [ 102 ('New Test', ""), 103 ('New Suite', ""), 104 ('New Resource', ""), 105 ] 106 self.file_menu_items.extend([ 107 ('Load Results', "javascript:load_results();"), 108 ('Save Results', qm.test.cmdline.QMTest.results_file_name), 109 ('Load Expectations', "javascript:load_expected_results();")]) 110 if self.HasModifiableExpectations(): 111 self.file_menu_items.extend([ 112 ('Save Expectations', 113 qm.test.cmdline.QMTest.expectations_file_name)]) 114 else: 115 self.file_menu_items.extend([('Save Expectations', "")]) 116 117 self.file_menu_items.extend([ 118 ('Load Context', "javascript:load_context();"), 119 ('Save Context', qm.test.cmdline.QMTest.context_file_name), 120 ('Exit', 'shutdown') 121 ]) 122 self.edit_menu_items = [ 123 ('Clear Results', "clear-results"), 124 ('Edit Context', "edit-context"), 125 ] 126 self.run_menu_items = [ 127 ('All Tests', "run-tests") 128 ] 129 self.view_menu_items = [ 130 ('Directory', "dir"), 131 ('Results', "show-results"), 132 ('Report', "") 133 ] 134 else: 135 136 self.file_menu_items = [ 137 ('New Test', ""), 138 ('New Suite', ""), 139 ('New Resource', ""), 140 ('Load Results', ""), 141 ('Save Results', ""), 142 ('Load Expectations', ""), 143 ('Save Expectations', ""), 144 ('Load Context', ""), 145 ('Save Context', ""), 146 ('Exit', 'shutdown') 147 ] 148 self.edit_menu_items = [ 149 ('Clear Results', ""), 150 ('Edit Context', ""), 151 ] 152 self.run_menu_items = [ 153 ('All Tests', "") 154 ] 155 self.view_menu_items = [ 156 ('Directory', "/test/dir"), 157 ('Results', ""), 158 ('Report', "/report/dir") 159 ] 160 161 self.help_menu_items = [ 162 ('Tutorial', "javascript:popup_tutorial();"), 163 ('QMTest Web Site', "http://www.qmtest.com") 164 ] 165 166 qm.web.DtmlPage.__init__(self, dtml_template, **attributes)
167 168
169 - def GetName(self):
170 """Return the name of the application.""" 171 172 return self.html_generator
173 174
175 - def MakeListingUrl(self):
176 return qm.web.WebRequest("dir", base=self.request).AsUrl()
177 178
179 - def GetMainPageUrl(self):
180 return self.MakeListingUrl()
181 182
183 - def GetDatabase(self):
184 """Returns the 'Database' in use. 185 186 returns -- The 'Database' in use.""" 187 188 return self.server.GetDatabase()
189 190
191 - def IsLabelInDirectory(self, id, directory):
192 """Returns true if 'id' is in 'directory'. 193 194 returns -- True if 'id' indicates a test contained in 195 'directory', or one of its subdirectories.""" 196 197 while len(id) >= len(directory): 198 if id == directory: 199 return 1 200 id = self.GetDatabase().SplitLabel(id)[0] 201 202 return 0
203 204
205 - def FormatId(self, id, type, style="basic"):
206 """Format 'id' as HTML. 207 208 'id' -- The name of a test or resource. 209 210 'type' -- The kind of item named by 'id'. Either 'resource', 211 'suite', or 'test'. 212 213 'style' -- The formatting style to use. One of 'plain', 214 'basic', 'navigation', or 'tree'. 215 216 returns -- A string containing HTML to use for 'id'.""" 217 218 script = "show-" + type 219 request = qm.web.WebRequest(script, self.request, True, id=id) 220 url = request.AsUrl() 221 parent_suite_id, name = self.GetDatabase().SplitLabel(id) 222 223 if style == "plain": 224 return '<span class="id">%s</span>' % id 225 226 elif style == "basic": 227 return '<a href="%s"><span class="id">%s</span></a>' % (url, id) 228 229 elif style == "navigation": 230 if parent_suite_id == "": 231 parent = "" 232 else: 233 parent = self.FormatId(parent_suite_id, "dir", style) 234 parent += id[len(parent_suite_id)] 235 return parent \ 236 + '<a href="%s"><span class="id">%s</span></a>' \ 237 % (url, name) 238 239 elif style == "tree": 240 return '<a href="%s"><span class="id">%s</span></a>' \ 241 % (url, name) 242 243 assert None
244 245
246 - def GetResultsByOutcome(self, results):
247 """Compute the tests in 'results' with each outcome. 248 249 'results' -- A sequence of 'Result' instances. 250 251 returns -- A dictionary mapping outcomes to the sequence of 252 tests that have the indicated outcome in 'results'.""" 253 254 results_by_outcome = {} 255 # At first, there are no results for any outcome. 256 for o in self.outcomes: 257 results_by_outcome[o] = [] 258 259 # Iterate through the results, adding each one to 260 # 'results_by_outcome'. 261 for r in results: 262 results_by_outcome[r.GetOutcome()].append(r) 263 264 return results_by_outcome
265 266
267 - def GetOutcomePercentages(self, results):
268 """Compute the percentage (by outcome) of the 'results'. 269 270 'results' -- A sequence of 'Result' instances. 271 272 returns -- A dictionary mapping outcomes to the percentage (as 273 a floating point number) of tests in 'results' that have 274 that outcome.""" 275 276 # Compute the total number of tests for which results are 277 # available. 278 total = len(results) 279 280 # Get the test results, organized by outcome. 281 results = self.GetResultsByOutcome(results) 282 283 # Compute the percentages. 284 percentages = {} 285 for o in self.outcomes: 286 if total: 287 percentages[o] = float(len(results[o])) / float(total) 288 else: 289 percentages[o] = 0.0 290 291 return percentages
292
293 - def HasModifiableExpectations(self):
294 """Return True if expectations are modifiable.""" 295 296 return type(self.server.GetExpectationDatabase()) in (PreviousTestRun,)
297 298
299 -class QMTestPage(DefaultDtmlPage):
300 """A 'QMTestPage' is a 'DtmlPage' for pages generated by QMTest. 301 302 A 'QMTestPage' automatically looks for DTML templates in the 303 directory that contains QMTest DTML templates.""" 304
305 - def __init__(self, dtml_template, server):
306 """Construct a new 'QMTestPage'. 307 308 'dtml_template' -- The file name of the DTML template, relative 309 to the directory that contains QMTest DTML templates. (Usually, 310 this is just a basename.) 311 312 'server' -- The 'QMTestServer' creating this page.""" 313 314 # Initialize the base class. 315 DefaultDtmlPage.__init__(self, 316 os.path.join("test", dtml_template), 317 server) 318 319 # Make the QMTest object available to the DTML pages. 320 self.qmtest = qm.test.cmdline.get_qmtest()
321 322
323 - def GenerateStartBody(self, decorations=1):
324 if decorations: 325 # If the server is in the midst of executing tests, it 326 # is not safe to edit tests, or to rerun the tests. 327 if not self.server.GetResultsStream().IsFinished(): 328 # The basic edit menu items are OK. 329 edit_menu_items = self.edit_menu_items[0:2] 330 # The run model should have no options. 331 run_menu_items = [ 332 ('Stop Tests', "stop-tests") 333 ] 334 # Otherwise, just use the values specified. 335 else: 336 edit_menu_items = self.edit_menu_items 337 run_menu_items = self.run_menu_items 338 339 # Figure out whether to use click-to-activate menus. 340 click_menus = 0 341 if qm.common.rc.has_option("common", "click_menus"): 342 try: 343 click_menus = qm.common.rc.getboolean("common", 344 "click_menus") 345 except ValueError: 346 pass 347 348 # Generate the navigation bar. 349 navigation_bar = \ 350 DefaultDtmlPage(os.path.join("test", "navigation-bar.dtml"), 351 self.server, 352 file_menu_items=self.file_menu_items, 353 edit_menu_items=edit_menu_items, 354 view_menu_items=self.view_menu_items, 355 run_menu_items=run_menu_items, 356 help_menu_items=self.help_menu_items, 357 click_menus = click_menus) 358 return "<body>%s<br />" % navigation_bar(self.request) 359 else: 360 return "<body>"
361 362 363
364 - def IsFinished(self):
365 """Return true iff no more results are forthcoming. 366 367 returns -- True if no more tests are running.""" 368 369 return 1
370 371
372 - def GetRefreshDelay(self):
373 """Returns the number of seconds to wait before refreshing the page. 374 375 returns -- The number of seconds to wait before refreshing this 376 page. A value of zero means that te page should never be 377 refreshed. This function is only called if 'IsFinished' returns 378 true.""" 379 380 return 0
381 382
383 - def GenerateHtmlHeader(self, description, headers=""):
384 """Return the header for an HTML document. 385 386 'description' -- A string describing this page. 387 388 'headers' -- Any additional HTML headers to place in the 389 '<head>' section of the HTML document.""" 390 391 # If the page isn't finished, automatically refresh it 392 # every few seconds.y 393 if not self.IsFinished(): 394 headers = (headers 395 + ('<meta http-equiv="refresh" content="%d" />' 396 % self.GetRefreshDelay())) 397 398 return DefaultDtmlPage.GenerateHtmlHeader(self, description, 399 headers)
400 401
402 - def GetExpectationUrl(self, id, expectation):
403 """Return the URL for setting the expectation associated with 'id'. 404 405 'id' -- The name of a test. 406 407 'expectation' -- The current expectation associated with the 408 test, or 'None' if there is no associated expectation.""" 409 410 return qm.web.WebRequest("set-expectation", 411 base=self.request, 412 id=id, 413 expectation=expectation or "None", 414 url=self.request.AsUrl()).AsUrl()
415 416 417 418
419 -class QMTestReportPage(DefaultDtmlPage):
420 """A 'QMTestReportPage' is a 'DtmlPage' for pages generated by QMTest. 421 422 A 'QMTestReportPage' automatically looks for DTML templates in the 423 directory that contains QMTest DTML templates.""" 424
425 - def __init__(self, dtml_template, server):
426 """Construct a new 'QMTestReportPage'. 427 428 'dtml_template' -- The file name of the DTML template, relative 429 to the directory that contains QMTest DTML templates. (Usually, 430 this is just a basename.) 431 432 'server' -- The 'QMTestServer' creating this page.""" 433 434 # Initialize the base class. 435 DefaultDtmlPage.__init__(self, 436 os.path.join("report", dtml_template), 437 server) 438 # Make the QMTest object available to the DTML pages. 439 self.qmtest = qm.test.cmdline.get_qmtest()
440 441
442 - def GetRunDatabase(self):
443 """Returns the 'RunDatabase' in use. 444 445 returns -- The 'RunDatabase' in use.""" 446 447 return self.server.GetRunDatabase()
448 449
450 - def GenerateStartBody(self, decorations=1):
451 if decorations: 452 edit_menu_items = self.edit_menu_items 453 run_menu_items = self.run_menu_items 454 455 # Figure out whether to use click-to-activate menus. 456 click_menus = 0 457 if qm.common.rc.has_option("common", "click_menus"): 458 try: 459 click_menus = qm.common.rc.getboolean("common", 460 "click_menus") 461 except ValueError: 462 pass 463 464 # Generate the navigation bar. 465 navigation_bar = \ 466 DefaultDtmlPage(os.path.join("test", "navigation-bar.dtml"), 467 self.server, 468 file_menu_items=self.file_menu_items, 469 edit_menu_items=edit_menu_items, 470 view_menu_items=self.view_menu_items, 471 run_menu_items=run_menu_items, 472 help_menu_items=self.help_menu_items, 473 click_menus = click_menus) 474 return "<body>%s<br />" % navigation_bar(self.request) 475 else: 476 return "<body>"
477 478 479
480 - def GenerateHtmlHeader(self, description, headers=""):
481 """Return the header for an HTML document. 482 483 'description' -- A string describing this page. 484 485 'headers' -- Any additional HTML headers to place in the 486 '<head>' section of the HTML document.""" 487 488 return DefaultDtmlPage.GenerateHtmlHeader(self, description, 489 headers)
490 491
492 - def GetResultURL(self, id, kind):
493 """Generate a URL for the result page for 'id'. 494 495 'id' -- The name of a test or resource. 496 497 'kind' -- either 'test' or 'resource'. 498 499 returns -- A url string for the result page for 'id'.""" 500 501 row = self.request.get('row', 'qmtest.run.uname') 502 script = {"test": "show-test", 503 "resource": "show-resource"}[kind] 504 request = qm.web.WebRequest(script, self.request, True, 505 id=id, 506 row=row) 507 return request.AsUrl()
508 509
510 - def FormatTimeIso(self, time):
511 512 return qm.common.format_time_iso(time)
513 514 515
516 -class ContextPage(QMTestPage):
517 """DTML page for setting the context.""" 518
519 - def __init__(self, server):
520 """Construct a new 'ContextPage'. 521 522 'server' -- The 'QMTestServer' creating this page.""" 523 524 QMTestPage.__init__(self, "context.dtml", server) 525 526 self.context = server.GetContext()
527 528 529
530 -class DirPage(QMTestPage):
531 """A test database directory page. 532 533 These attributes are available in DTML: 534 535 'path' -- The label directory that is being displayed. 536 537 'subdirs' -- A sequence of labels giving the subdirectories of 538 this directory. 539 540 'test_ids' -- A sequence of labels giving the tests in this 541 directory. 542 543 'suite_ids' -- A sequence of labels giving the suites in this 544 directory. 545 546 'resource_ids' -- A sequence of labels giving the resources in 547 this directory.""" 548 549 SORT_NAME = 'name' 550 """Sort by name.""" 551 552 SORT_OUTCOME = 'outcome' 553 """Sort by outcome.""" 554 555 SORT_EXPECTATION = 'expectation' 556 """Sort by expectation. In other words, put unexpected outcomes 557 before expected outcomes.""" 558 559 SORT_KINDS = [ SORT_NAME, SORT_OUTCOME, SORT_EXPECTATION ] 560 """The kinds of sorting available.""" 561
562 - def __init__(self, server, path):
563 """Construct a 'DirPage'. 564 565 'server' -- The 'QMTestServer' creating this page. 566 567 'path' -- The label directory to display.""" 568 569 # Initialize the base class. 570 QMTestPage.__init__(self, "dir.dtml", server) 571 572 self.path = path 573 self.database = server.GetDatabase() 574 self.subdir_ids = self.database.GetSubdirectories(path) 575 self.subdir_ids = map(lambda l: self.database.JoinLabels(path, l), 576 self.subdir_ids) 577 self.test_ids = self.database.GetTestIds(path, scan_subdirs=0) 578 self.suite_ids = self.database.GetSuiteIds(path, scan_subdirs=0) 579 # Do not show implicit suites. Otherwise, there are two 580 # entries for a directory: one as a subdirectory entry, and 581 # the other as a test suite. 582 self.suite_ids = filter(lambda s, d=self.database: \ 583 not d.GetSuite(s).IsImplicit(), 584 self.suite_ids) 585 self.resource_ids = self.database.GetResourceIds(path, scan_subdirs=0) 586 587 # Get the results to date. 588 results_stream = server.GetResultsStream() 589 # It is important that we ask for IsFinished before asking 590 # for GetTestResults. The stream could be finished between 591 # the two calls, and it is better to show all the results but 592 # claim they are incomplete than to show only some of the 593 # results and claim they are complete. 594 self.__is_finished = results_stream.IsFinished() 595 self.test_results = results_stream.GetTestResults() 596 self.expected_outcomes = server.GetExpectedOutcomes() 597 self.expectation_is_modifiable = \ 598 type(server.GetExpectationDatabase()) in (PreviousTestRun,) 599 600 # Make it easy for the DTML page to get at all the outcomes. 601 #self.outcomes = Result.outcomes + [self.EXPECTED] 602 603 # Provide a menu choice to allow running all of the tests in 604 # this directory. 605 if self.server.GetRunDatabase(): 606 self.run_menu_items.append(("This Directory", "")) 607 else: 608 self.run_menu_items.append(("This Directory", "javascript:run_dir();"))
609 610
611 - def GetRunUrl(self):
612 """Return the URL for running this directory.""" 613 614 return qm.web.WebRequest("run-tests", 615 self.request, 616 ids=self.path).AsUrl()
617 618
619 - def GetTestResultsForDirectory(self, directory):
620 """Return all of the test results for tests in 'directory'. 621 622 'directory' -- A string giving the label for a directory. 623 624 returns -- A sequence of 'Result' instances corresponding to 625 results for tests from the indicated directory.""" 626 627 # If we are in report mode, fetch the results from the run database. 628 test_run = self.request.get('test_run') 629 run_db = self.server.GetRunDatabase() 630 if test_run and run_db: 631 return run_db.GetAllRuns()[int(test_run)].GetAllResults(directory) 632 633 # Else use the test_results. 634 if directory == "": 635 return self.test_results.values() 636 else: 637 return [r for r in self.test_results.values() 638 if self.IsLabelInDirectory(r.GetId(), directory)]
639 640
641 - def GetUnexpectedResultsByOutcome(self, results):
642 """Compute the tests in 'results' with each outcome. 643 644 'results' -- A sequence of 'Result' instances. 645 646 returns -- A dictionary mapping outcomes to the results with 647 that outcome -- and for which that outcome is unexpected. 648 The (fake) outcome 'self.EXPECTED' is mapped to expected 649 results.""" 650 651 results_by_outcome = {} 652 # At first, there are no results for any outcome. 653 for o in self.outcomes: 654 results_by_outcome[o] = [] 655 656 for r in results: 657 # See what outcome was expected. 658 expectation = self.GetExpectation(r.GetId()) or Result.PASS 659 # Update results_by_outcome. 660 if r.GetOutcome() != expectation: 661 results_by_outcome[r.GetOutcome()].append(r) 662 else: 663 results_by_outcome[self.EXPECTED].append(r) 664 665 return results_by_outcome
666 667
668 - def GetUnexpectedOutcomePercentages(self, results):
669 """Compute percentages of unexpected 'results'. 670 671 'results' -- A sequence of 'Result' instances. 672 673 returns -- A dictionary mapping the 'EXPECTATION_KINDS' to the 674 percentage (as a floating point number) of tests in 'results' 675 that have that expectation.""" 676 677 # Compute the total number of tests for which results are 678 # available. 679 total = len(results) 680 681 # Get the test results, organized by outcome. 682 results_by_outcome \ 683 = self.GetUnexpectedResultsByOutcome(results) 684 685 # Compute the absolute number of tests in each category. 686 percentages = {} 687 percentages[self.POSITIVE_UNEXPECTED] \ 688 = len(results_by_outcome[Result.PASS]) 689 percentages[self.NEGATIVE_UNEXPECTED] \ 690 = (len(results_by_outcome[Result.FAIL]) 691 + len(results_by_outcome[Result.ERROR]) 692 + len(results_by_outcome[Result.UNTESTED])) 693 percentages[self.EXPECTED] \ 694 = len(results_by_outcome[self.EXPECTED]) 695 696 # And the corresponding percentages. 697 for e in self.EXPECTATION_KINDS: 698 if percentages[e]: 699 percentages[e] = float(percentages[e]) / float(total) 700 else: 701 percentages[e] = 0.0 702 703 return percentages
704 705
706 - def CountUnexpected(self, results):
707 """Count the unexpected 'results'. 708 709 'results' -- A dictionary of the form returned by 710 'GetUnexpectedResultsByOutcome'. 711 712 returns -- The total number of unexpected results.""" 713 714 total = 0 715 # Go through all the outcomes except 'EXPECTED'. 716 for o in Result.outcomes: 717 total += len(results[o]) 718 719 return total
720 721
722 - def GetResultURL(self, id, kind):
723 """Generate a URL for the result page for 'id'. 724 725 'id' -- The name of a test or resource. 726 727 'kind' -- either 'test' or 'resource'. 728 729 returns -- A url string for the result page for 'id'.""" 730 731 script = {"test": "show-test", 732 "resource": "show-resource"}[kind] 733 request = qm.web.WebRequest(script, base=self.request, id=id) 734 return request.AsUrl()
735 736
737 - def GetTests(self, sort):
738 """Return information about all of the tests. 739 740 'sort' -- One of the 'SORT_KINDS' indicating how the results 741 should be sorted. 742 743 returns -- A sequence of 'Item' instances 744 corresponding to all of the tests in this diretory.""" 745 746 # There is no information yet. 747 tests = [] 748 749 # Iterate through each of the tests. 750 for id in self.test_ids: 751 outcome = self.GetTestOutcome(id) 752 expectation = self.GetExpectation(id) 753 tests.append(Item(id, 754 outcome=outcome, 755 expectation=expectation)) 756 757 if sort == self.SORT_NAME: 758 # The tests are already sorted by name. 759 pass 760 elif sort == self.SORT_OUTCOME: 761 # Sort the test by outcome; interesting outcomes come first. 762 buckets = {} 763 for o in Result.outcomes + [None]: 764 buckets[o] = [] 765 766 # Go through the tests dropping each in the right bucket. 767 for t in tests: 768 buckets[t.outcome].append(t) 769 770 # Combine the buckets. 771 tests = [] 772 for o in Result.outcomes + [None]: 773 tests += buckets[o] 774 elif sort == self.SORT_EXPECTATION: 775 # Sort the test by expectations; unexpected outcomes come 776 # first. 777 buckets = {} 778 for o in ['UNEXPECTED', self.EXPECTED, None]: 779 buckets[o] = [] 780 781 # Go through the tests dropping each in the right bucket. 782 for t in tests: 783 if (t.outcome == (t.expectation or Result.PASS)): 784 buckets[self.EXPECTED].append(t) 785 elif t.outcome: 786 buckets['UNEXPECTED'].append(t) 787 else: 788 buckets[None].append(t) 789 790 # Combine the buckets. 791 tests = [] 792 for o in ['UNEXPECTED', self.EXPECTED, None]: 793 tests += buckets[o] 794 else: 795 # Ignore the sort request. (We cannot assert that this case 796 # never happens because users can type any URL they like 797 # into their web browser.) 798 pass 799 800 return tests
801 802
803 - def GetTestOutcome(self, test_id):
804 """Return the 'Result' for 'test_id'. 805 806 'test_id' -- The name of the test whose result is requested. 807 808 'result' -- The result associated with the 'test_id', or 809 'None' if no result is available.""" 810 811 test_run = self.request.get('test_run') 812 run_db = self.server.GetRunDatabase() 813 if test_run and run_db: 814 result = run_db.GetAllRuns()[int(test_run)].GetResult(test_id) 815 else: 816 result = self.test_results.get(test_id) 817 return result and result.GetOutcome()
818 819
820 - def GetDetailURL(self, test_id):
821 """Return the detail URL for 'test_id'. 822 823 'test_id' -- The name of the test. 824 825 returns -- The URL that contains details about the 'test_id'.""" 826 827 return qm.web.WebRequest("show-result", 828 self.request, 829 True, 830 id=test_id).AsUrl()
831 832
833 - def GetExpectation(self, test_id):
834 """Return the expected outcome for 'test_id'. 835 836 'test_id' -- The name of the test. 837 838 returns -- A string giving the expected outcome for 'test_id', 839 or 'None' if there is no expectation.""" 840 841 return self.expected_outcomes.get(test_id)
842 843
844 - def GetSortURL(self, sort):
845 """Get the URL for this page, but sorted as indicated. 846 847 'sort' -- One of the 'SORT_KINDS'. 848 849 returns -- A URL indicating this page, but sorted as 850 indicated.""" 851 852 return qm.web.WebRequest("show-dir", 853 base=self.request, 854 id=self.path, 855 sort=sort).AsUrl()
856
857 - def IsFinished(self):
858 """Return true iff no more results are forthcoming. 859 860 returns -- True if no more tests are running.""" 861 862 return self.__is_finished
863 864
865 - def GetRefreshDelay(self):
866 """Returns the number of seconds to wait before refreshing the page. 867 868 returns -- The number of seconds to wait before refreshing this 869 page. A value of zero means that te page should never be 870 refreshed. This function is only called if 'IsFinished' returns 871 true.""" 872 873 if len(self.test_results.items()) < 50: 874 return 10 875 else: 876 return 30
877 878
879 -class DirReportPage(QMTestReportPage):
880 """A run database directory page. 881 882 These attributes are available in DTML: 883 884 'path' -- The label directory that is being displayed. 885 886 'subdirs' -- A sequence of labels giving the subdirectories of 887 this directory. 888 889 'test_ids' -- A sequence of labels giving the tests in this 890 directory. 891 892 'suite_ids' -- A sequence of labels giving the suites in this 893 directory. 894 895 'resource_ids' -- A sequence of labels giving the resources in 896 this directory.""" 897 898 SORT_NAME = 'name' 899 """Sort by name.""" 900 901 SORT_OUTCOME = 'outcome' 902 """Sort by outcome.""" 903 904 SORT_EXPECTATION = 'expectation' 905 """Sort by expectation. In other words, put unexpected outcomes 906 before expected outcomes.""" 907 908 SORT_KINDS = [ SORT_NAME, SORT_OUTCOME, SORT_EXPECTATION ] 909 """The kinds of sorting available.""" 910
911 - def __init__(self, server, path):
912 """Construct a 'DirPage'. 913 914 'server' -- The 'QMTestServer' creating this page. 915 916 'path' -- The label directory to display.""" 917 918 # Initialize the base class. 919 QMTestReportPage.__init__(self, "dir.dtml", server) 920 921 self.path = path 922 database = server.GetDatabase() 923 self.database = database 924 self.run_db = server.GetRunDatabase() 925 self.subdir_ids = [database.JoinLabels(path, l) 926 for l in database.GetSubdirectories(path)] 927 self.test_ids = self.database.GetTestIds(path, scan_subdirs=0) 928 self.suite_ids = [s for s in database.GetSuiteIds(path, scan_subdirs=0) 929 if not database.GetSuite(s).IsImplicit()] 930 self.resource_ids = self.database.GetResourceIds(path, scan_subdirs=0)
931 932
933 - def GetItems(self, kind = Result.TEST):
934 """Return information about all of the items. 935 936 returns -- A sequence of 'Item' instances 937 corresponding to all of the tests in this diretory.""" 938 939 # There is no information yet. 940 items = [] 941 942 # Iterate through each of the tests. 943 test_runs = len(self.run_db.GetAllRuns()) 944 for id in self.test_ids: 945 outcomes = self.run_db.GetOutcomes(id, kind) 946 if outcomes[Result.PASS] == test_runs: 947 outcome = Result.PASS 948 outcome_class = 'qmtest_pass' 949 elif outcomes[Result.FAIL] == test_runs: 950 outcome = Result.FAIL 951 outcome_class = 'qmtest_fail' 952 elif outcomes[Result.UNTESTED] == test_runs: 953 outcome = Result.UNTESTED 954 outcome_class = 'qmtest_untested' 955 elif outcomes[Result.ERROR] == test_runs: 956 outcome = Result.ERROR 957 outcome_class = 'qmtest_error' 958 else: 959 outcome = 'MIXED' 960 outcome_class = 'qmtest_mixed' # FIXME: add more detail here 961 items.append(Item(id, 962 outcome=outcome, 963 outcome_class=outcome_class)) 964 965 return items
966 967
968 - def MakeTestRunUrl(self, test_run):
969 """Return the URL for navigating a particular test run.""" 970 971 return qm.web.WebRequest("/test/dir", 972 self.request, True, 973 test_run=test_run, 974 id=self.path).AsUrl()
975 976 977 978
979 -class ShowItemReportPage(QMTestReportPage):
980 """DTML page for showing tests and resources.""" 981
982 - def __init__(self, server, item, type, field_errors={}):
983 """Construct a new DTML context. 984 985 These parameters are also available in DTML under the same name: 986 987 'server' -- The 'QMTestServer' creating this page. 988 989 'item' -- The 'TestDescriptor' or 'ResourceDescriptor' for the 990 test being shown. 991 992 'type' -- Either "test" or "resource". 993 994 'field_errors' -- A map from field names to corresponding error 995 messages.""" 996 997 # Initialize the base class. 998 QMTestReportPage.__init__(self, "show.dtml", server) 999 self.item = item 1000 self.fields = item.GetClassArguments() 1001 assert type in ["test", "resource"] 1002 self.type = type 1003 self.field_errors = field_errors
1004 1005
1006 - def GetTitle(self):
1007 """Return the page title for this page.""" 1008 1009 url = self.request.GetScriptName() 1010 title = {"show-test": "Show Test Report ", 1011 "show-resource": "Show Resource Report "}[url] 1012 return title + self.item.GetId()
1013 1014
1015 - def FormatFieldValue(self, field):
1016 """Return an HTML rendering of the value for 'field'.""" 1017 1018 # Extract the field value. 1019 arguments = self.item.GetArguments() 1020 field_name = field.GetName() 1021 try: 1022 value = arguments[field_name] 1023 except KeyError: 1024 # Use the default value if none is provided. 1025 value = field.GetDefaultValue() 1026 return field.FormatValueAsHtml(self.server, value, "full")
1027 1028
1029 - def GetClassDescription(self):
1030 """Return a full description of the test or resource class. 1031 1032 returns -- The description, formatted as HTML.""" 1033 1034 d = qm.extension.get_class_description(self.item.GetClass()) 1035 return qm.web.format_structured_text(d)
1036 1037
1038 - def GetBriefClassDescription(self):
1039 """Return a brief description of the test or resource class. 1040 1041 returns -- The brief description, formatted as HTML.""" 1042 1043 d = qm.extension.get_class_description(self.item.GetClass(), 1044 brief=1) 1045 return qm.web.format_structured_text(d)
1046 1047
1048 - def MakeShowUrl(self):
1049 """Return the URL for showing this item.""" 1050 1051 return qm.web.WebRequest("show-" + self.type, 1052 self.request, True, 1053 id=self.item.GetId()).AsUrl()
1054 1055
1056 - def GetDetailUrl(self, test_run):
1057 """Return the detail URL for a test. 1058 1059 'test_id' -- The name of the test. 1060 1061 returns -- The URL that contains details about the 'test_id'.""" 1062 1063 return qm.web.WebRequest("show-result", 1064 self.request, True, 1065 id=self.item.GetId(), 1066 test_run=test_run).AsUrl()
1067 1068
1069 - def GetResults(self, key=None):
1070 """Return the results from all runs that correpond to the current id.""" 1071 1072 result_set = [] 1073 test_runs = self.server.GetRunDatabase().GetAllRuns() 1074 for r in range(len(test_runs)): 1075 k = test_runs[r].GetAnnotation(key or self.request['row']) 1076 result = None 1077 try: 1078 result = test_runs[r].GetResult(self.item.GetId(), self.type) 1079 except KeyError: 1080 pass 1081 result_set.append(Item(k, test_run=r, result=result)) 1082 return result_set
1083 1084 1085
1086 -class LoadContextPage(QMTestPage):
1087 """DTML page for uploading a context.""" 1088 1089 title = "Load Context" 1090 """The title for the page.""" 1091 1092 heading = "Load the context from a file." 1093 """The heading printed across the top of the page.""" 1094 1095 prompt = "The file from which to load the context." 1096 """The prompt for the file name.""" 1097 1098 submit_url = "submit-context-file" 1099 """The URL to which the file should be submitted.""" 1100
1101 - def __init__(self, server):
1102 """Construct a new 'LoadContextPage'. 1103 1104 'server' -- The 'QMTestServer' creating this page.""" 1105 1106 QMTestPage.__init__(self, "load.dtml", server)
1107 1108 1109
1110 -class LoadExpectationsPage(QMTestPage):
1111 """DTML page for uploading a context.""" 1112 1113 title = "Load Expectations" 1114 """The title for the page.""" 1115 1116 heading = "Load expectations from a file." 1117 """The heading printed across the top of the page.""" 1118 1119 prompt = "The file from which to load expectations.""" 1120 """The prompt for the file name.""" 1121 1122 submit_url = "submit-expectations" 1123 """The URL to which the file should be submitted.""" 1124
1125 - def __init__(self, server):
1126 """Construct a new 'LoadExpectationsPage'. 1127 1128 'server' -- The 'QMTestServer' creating this page.""" 1129 1130 QMTestPage.__init__(self, "load.dtml", server)
1131 1132 1133
1134 -class LoadResultsPage(QMTestPage):
1135 """DTML page for uploading a context.""" 1136 1137 title = "Load Results" 1138 """The title for the page.""" 1139 1140 heading = "Load results from a file." 1141 """The heading printed across the top of the page.""" 1142 1143 prompt = "The file from which to load the results.""" 1144 """The prompt for the file name.""" 1145 1146 submit_url = "submit-results" 1147 """The URL to which the file should be submitted.""" 1148
1149 - def __init__(self, server):
1150 """Construct a new 'LoadContextPage'. 1151 1152 'server' -- The 'QMTestServer' creating this page.""" 1153 1154 QMTestPage.__init__(self, "load.dtml", server)
1155 1156 1157
1158 -class NewItemPage(QMTestPage):
1159 """Page for creating a new test or resource.""" 1160
1161 - def __init__(self, 1162 server, 1163 type, 1164 item_id="", 1165 class_name="", 1166 field_errors={}):
1167 """Create a new DTML context. 1168 1169 'type' -- Either "test" or "resource". 1170 1171 'server' -- The 'QMTestServer' creating this page. 1172 1173 'item_id' -- The item ID to show. 1174 1175 'class_name' -- The class name to show. 1176 1177 'field_errors' -- A mapping of error messages for fields. Keys 1178 may be "_id" or "_class".""" 1179 1180 # Initialize the base class. 1181 QMTestPage.__init__(self, "new.dtml", server) 1182 # Set up attributes. 1183 assert type in ["test", "resource"] 1184 self.database = server.GetDatabase() 1185 self.type = type 1186 self.item_id = item_id 1187 self.class_name = class_name 1188 if type == "test": 1189 self.class_names = self.database.GetTestClassNames() 1190 elif type == "resource": 1191 self.class_names = self.database.GetResourceClassNames() 1192 self.field_errors = field_errors
1193 1194
1195 - def GetTitle(self):
1196 """Return the title this page.""" 1197 1198 return "Create a New %s" % string.capwords(self.type)
1199 1200
1201 - def GetClassDescriptions(self):
1202 """Return a description of the available classes. 1203 1204 returns -- Structured text describing each of the available 1205 test or resource classes.""" 1206 1207 desc = "**Available Classes**\n\n" 1208 for n in self.class_names: 1209 c = qm.test.base.get_extension_class(n, self.type, 1210 self.database) 1211 d = qm.extension.get_class_description(c, brief=1) 1212 desc = desc + " * " + n + "\n\n " + d + "\n\n" 1213 1214 return desc
1215 1216
1217 - def MakeSubmitUrl(self):
1218 """Return the URL for submitting the form. 1219 1220 The URL is for the script 'create-test' or 'create-resource' as 1221 appropriate.""" 1222 1223 return qm.web.WebRequest("create-" + self.type, 1224 base=self.request).AsUrl()
1225 1226 1227
1228 -class NewSuitePage(QMTestPage):
1229 """Page for creating a new test suite.""" 1230
1231 - def __init__(self, server, suite_id="", field_errors={}):
1232 """Create a new DTML context. 1233 1234 'server' -- The 'QMTestServer' creating this page. 1235 1236 'suite_id' -- Initial value for the new test suite ID field. 1237 1238 'field_errors' -- A mapping of error messages to fields. If 1239 empty, there are no errors.""" 1240 1241 # Initialize the base class. 1242 QMTestPage.__init__(self, "new-suite.dtml", server) 1243 # Set up attributes. 1244 self.suite_id = suite_id 1245 self.field_errors = field_errors
1246 1247 1248
1249 -class ResultPage(QMTestPage):
1250 """DTML page for showing result detail.""" 1251
1252 - def __init__(self, server, result):
1253 """Construct a new 'ResultPage' 1254 1255 'server' -- The 'QMTestServer' creating this page. 1256 1257 'result' -- The result to display.""" 1258 1259 QMTestPage.__init__(self, "result.dtml", server) 1260 self.result = result 1261 if result.GetKind() == Result.TEST: 1262 self.run_menu_items.append(("This Test", 1263 "javascript:run_test();"))
1264
1265 - def GetResultURL(self, id):
1266 1267 return qm.web.WebRequest("show-result", 1268 base = self.request, 1269 id = id).AsUrl()
1270 1271
1272 - def GetRunURL(self):
1273 1274 return qm.web.WebRequest("run-tests", 1275 base = self.request, 1276 ids = self.result.GetId()).AsUrl()
1277 1278 1279
1280 -class SetExpectationPage(QMTestPage):
1281 """DTML page for setting the expectation associated with a test.""" 1282
1283 - def __init__(self, server, id):
1284 """Construct a new 'SetExpectationPage'. 1285 1286 'server' -- The 'QMTestServer' creating this page. 1287 1288 'id' -- The name of the test whose expectation is being set.""" 1289 1290 QMTestPage.__init__(self, "set-expectation.dtml", server) 1291 self.outcomes = ["None"] + Result.outcomes
1292 1293 1294
1295 -class ShowItemPage(QMTestPage):
1296 """DTML page for showing and editing tests and resources.""" 1297
1298 - def __init__(self, server, item, edit, new, type, field_errors={}):
1299 """Construct a new DTML context. 1300 1301 These parameters are also available in DTML under the same name: 1302 1303 'server' -- The 'QMTestServer' creating this page. 1304 1305 'item' -- The 'TestDescriptor' or 'ResourceDescriptor' for the 1306 test being shown. 1307 1308 'edit' -- True for editing the item; false for displaying it 1309 only. 1310 1311 'new' -- True for editing a newly-created item ('edit' is then 1312 also true). 1313 1314 'type' -- Either "test" or "resource". 1315 1316 'field_errors' -- A map from field names to corresponding error 1317 messages.""" 1318 1319 # Initialize the base class. 1320 QMTestPage.__init__(self, "show.dtml", server) 1321 # Set up attributes. 1322 self.__database = server.GetDatabase() 1323 self.item = item 1324 self.fields = item.GetClassArguments() 1325 self.edit = edit 1326 self.new = new 1327 assert type in ["test", "resource"] 1328 self.type = type 1329 self.field_errors = field_errors 1330 1331 if self.__database.IsModifiable(): 1332 self.edit_menu_items.append(("Edit %s" % string.capitalize(type), 1333 "javascript:edit_item();")) 1334 self.edit_menu_items.append(("Delete %s" % string.capitalize(type), 1335 "javascript:delete_item();")) 1336 1337 if type == "test" and not edit: 1338 self.run_menu_items.append(("This Test", "javascript:run_test();"))
1339 1340
1341 - def GetTitle(self):
1342 """Return the page title for this page.""" 1343 1344 # Map the scriptname to a nicely-formatted title. 1345 url = self.request.GetScriptName() 1346 title = { 1347 "show-test": "Show Test", 1348 "edit-test": "Edit Test", 1349 "create-test": "New Test", 1350 "show-resource": "Show Resource", 1351 "edit-resource": "Edit Resource", 1352 "create-resource": "New Resource", 1353 }[url] 1354 # Show the item's ID too. 1355 title = title + " " + self.item.GetId() 1356 return title
1357 1358
1359 - def FormatFieldValue(self, field):
1360 """Return an HTML rendering of the value for 'field'.""" 1361 1362 # Extract the field value. 1363 arguments = self.item.GetArguments() 1364 field_name = field.GetName() 1365 try: 1366 value = arguments[field_name] 1367 except KeyError: 1368 # Use the default value if none is provided. 1369 value = field.GetDefaultValue() 1370 # Format it appropriately. 1371 server = self.server 1372 if self.edit: 1373 if field.IsHidden(): 1374 return field.FormatValueAsHtml(server, value, "hidden") 1375 elif field.IsReadOnly(): 1376 # For read-only fields, we still need a form input, but 1377 # the user shouldn't be able to change anything. Use a 1378 # hidden input, and display the contents as if this 1379 # wasn't an editing form. 1380 return field.FormatValueAsHtml(server, value, "hidden") \ 1381 + field.FormatValueAsHtml(server, value, "full") 1382 else: 1383 return field.FormatValueAsHtml(server, value, "edit") 1384 else: 1385 return field.FormatValueAsHtml(server, value, "full")
1386 1387
1388 - def GetClassDescription(self):
1389 """Return a full description of the test or resource class. 1390 1391 returns -- The description, formatted as HTML.""" 1392 1393 d = qm.extension.get_class_description(self.item.GetClass()) 1394 return qm.web.format_structured_text(d)
1395 1396
1397 - def GetBriefClassDescription(self):
1398 """Return a brief description of the test or resource class. 1399 1400 returns -- The brief description, formatted as HTML.""" 1401 1402 d = qm.extension.get_class_description(self.item.GetClass(), 1403 brief=1) 1404 return qm.web.format_structured_text(d)
1405 1406
1407 - def MakeEditUrl(self):
1408 """Return the URL for editing this item.""" 1409 1410 return qm.web.WebRequest("edit-" + self.type, 1411 base=self.request, 1412 id=self.item.GetId()).AsUrl()
1413 1414
1415 - def MakeRunUrl(self):
1416 """Return the URL for running this item.""" 1417 1418 return qm.web.WebRequest("run-tests", 1419 base=self.request, 1420 ids=self.item.GetId()).AsUrl()
1421 1422
1423 - def MakeShowUrl(self):
1424 """Return the URL for showing this item.""" 1425 1426 return qm.web.WebRequest("show-" + self.type, 1427 base=self.request, 1428 id=self.item.GetId()).AsUrl()
1429 1430
1431 - def MakeSubmitUrl(self):
1432 """Return the URL for submitting edits.""" 1433 1434 return qm.web.WebRequest("submit-" + self.type, 1435 base=self.request).AsUrl()
1436 1437
1438 - def MakeDeleteScript(self):
1439 """Make a script to confirm deletion of the test or resource. 1440 1441 returns -- JavaScript source to handle deletion of the 1442 test or resource.""" 1443 1444 item_id = self.item.GetId() 1445 delete_url = qm.web.make_url("delete-" + self.type, 1446 base_request=self.request, 1447 id=item_id) 1448 message = """ 1449 <p>Are you sure you want to delete the %s %s?</p> 1450 """ % (self.type, item_id) 1451 return self.server.MakeConfirmationDialog(message, delete_url)
1452 1453 1454
1455 -class ShowSuitePage(QMTestPage):
1456 """Page for displaying the contents of a test suite.""" 1457
1458 - def __init__(self, server, suite, edit, is_new_suite):
1459 """Construct a new DTML context. 1460 1461 'server' -- The 'QMTestServer' creating this page. 1462 1463 'suite' -- The 'Suite' instance to display. 1464 1465 'edit' -- If true, display controls for editing the suite. 1466 1467 'is_new_suite' -- If true, the suite being displayed is being 1468 created at this time.""" 1469 1470 # Initialize the base class. 1471 QMTestPage.__init__(self, "suite.dtml", server) 1472 1473 # It does not make sense to display a new suite without being 1474 # able to edit it; there is nothing to show. 1475 assert edit or not is_new_suite 1476 1477 # Set up attributes. 1478 database = server.GetDatabase() 1479 self.suite = suite 1480 self.test_ids = suite.GetTestIds() 1481 self.suite_ids = suite.GetSuiteIds() 1482 self.edit = edit 1483 self.is_new_suite = is_new_suite 1484 1485 if not suite.IsImplicit() and database.IsModifiable(): 1486 self.edit_menu_items.append(("Edit Suite", 1487 "javascript:edit_suite();")) 1488 self.edit_menu_items.append(("Delete Suite", 1489 "javascript:delete_suite();")) 1490 1491 if not edit: 1492 self.run_menu_items.append(("This Suite", 1493 "javascript:run_suite();")) 1494 1495 if edit: 1496 # Find the directory path containing this suite. 1497 (dirname, basename) = self.GetDatabase().SplitLabel(suite.GetId()) 1498 1499 # Construct a list of all test IDs, relative to the suite, 1500 # that are not explicitly included in the suite. 1501 excluded_test_ids = database.GetTestIds(dirname) 1502 for test_id in self.test_ids: 1503 if test_id in excluded_test_ids: 1504 excluded_test_ids.remove(test_id) 1505 # Make controls for adding or removing test IDs. 1506 self.test_id_controls = qm.web.make_choose_control( 1507 "test_ids", 1508 "Included Tests", 1509 self.test_ids, 1510 "Available Tests", 1511 excluded_test_ids) 1512 1513 # Likewise for suite IDs. 1514 excluded_suite_ids = database.GetSuiteIds(dirname) 1515 for suite_id in self.suite_ids: 1516 if suite_id in excluded_suite_ids: 1517 excluded_suite_ids.remove(suite_id) 1518 # Don't show the suite as a candidate for inclusion in 1519 # itself. 1520 self_suite_id = basename 1521 if self_suite_id in excluded_suite_ids: 1522 excluded_suite_ids.remove(self_suite_id) 1523 # Make controls for adding or removing suite IDs. 1524 self.suite_id_controls = qm.web.make_choose_control( 1525 "suite_ids", 1526 "Included Suites", 1527 self.suite_ids, 1528 "Available Suites", 1529 excluded_suite_ids)
1530 1531
1532 - def MakeEditUrl(self):
1533 """Return the URL for editing this suite.""" 1534 1535 return qm.web.WebRequest("edit-suite", 1536 base=self.request, 1537 id=self.suite.GetId()) \ 1538 .AsUrl()
1539 1540
1541 - def MakeRunUrl(self):
1542 """Return the URL for running this suite.""" 1543 1544 return qm.web.WebRequest("run-tests", 1545 base=self.request, 1546 ids=self.suite.GetId()) \ 1547 .AsUrl()
1548 1549
1550 - def MakeDeleteScript(self):
1551 """Make a script to confirm deletion of the suite. 1552 1553 returns -- JavaScript source for a function, 'delete_script', 1554 which shows a popup confirmation window.""" 1555 1556 suite_id = self.suite.GetId() 1557 delete_url = qm.web.make_url("delete-suite", 1558 base_request=self.request, 1559 id=suite_id) 1560 message = """ 1561 <p>Are you sure you want to delete the suite %s?</p> 1562 """ % suite_id 1563 return self.server.MakeConfirmationDialog(message, delete_url)
1564 1565 1566
1567 -class StorageResultsStream(ResultStream):
1568 """A 'StorageResultsStream' stores results. 1569 1570 A 'StorageResultsStream' does not write any output. It simply 1571 stores the results for future display.""" 1572
1573 - def __init__(self):
1574 """Construct a 'StorageResultsStream'.""" 1575 1576 super(StorageResultsStream, self).__init__({}) 1577 self.__test_results = {} 1578 self.__test_results_in_order = [] 1579 self.__resource_results = {} 1580 # The stream is not finished yet. 1581 self.__is_finished = 0 1582 # And there are no annotations yet. 1583 self.__annotations = {} 1584 1585 # Create a lock for synchronization between the test execution 1586 # thread (which will call methods like 'WriteResults' and 1587 # 'Summarize') and the GUI thread (which will call 1588 # 'GetTestResults' and 'IsFinished'). 1589 self.__lock = Lock()
1590 1591
1592 - def GetAnnotations(self):
1593 """Return the annotations for this run.""" 1594 1595 return self.__annotations
1596 1597
1598 - def WriteAnnotation(self, key, value):
1599 1600 self.__annotations[key] = value
1601 1602
1603 - def WriteResult(self, result):
1604 """Output a test result. 1605 1606 'result' -- A 'Result'.""" 1607 1608 self.__lock.acquire() 1609 try: 1610 if result.GetKind() == Result.TEST: 1611 self.__test_results[result.GetId()] = result 1612 self.__test_results_in_order.append(result) 1613 else: 1614 self.__resource_results[result.GetId()] = result 1615 finally: 1616 self.__lock.release()
1617 1618
1619 - def Summarize(self):
1620 """Output summary information about the results. 1621 1622 When this method is called, the test run is complete. Summary 1623 information should be displayed for the user, if appropriate. 1624 Any finalization, such as the closing of open files, should 1625 also be performed at this point. 1626 1627 Derived class methods may override this method. They should, 1628 however, invoke this version before returning.""" 1629 1630 # Mark the stream as finished. 1631 self.__lock.acquire() 1632 ResultStream.Summarize(self) 1633 self.__is_finished = 1 1634 self.__lock.release()
1635 1636
1637 - def Start(self, test_ids):
1638 """Start collecting results. 1639 1640 'test_ids' -- The names of the tests that we are about to run. 1641 1642 Start collecting new results. Discard results for the 1643 'test_ids', but not for other tests.""" 1644 1645 self.__lock.acquire() 1646 self.__is_finished = 0 1647 # Go through all of the tests we are about to run and remove 1648 # corresponding results. 1649 for id in test_ids: 1650 if self.__test_results.has_key(id): 1651 del self.__test_results[id] 1652 self.__test_results_in_order \ 1653 = filter(lambda r, rs=self.__test_results: \ 1654 rs.has_key(r.GetId()), 1655 self.__test_results_in_order) 1656 self.__lock.release()
1657 1658
1659 - def IsFinished(self):
1660 """Return true iff no more results are forthcoming. 1661 1662 returns -- True if no more results will be written to this 1663 stream.""" 1664 1665 self.__lock.acquire() 1666 finished = self.__is_finished 1667 self.__lock.release() 1668 return finished
1669 1670
1671 - def GetTestResults(self):
1672 """Return the accumulated test results. 1673 1674 returns -- A dictionary mapping test names to 'Result' objects.""" 1675 1676 self.__lock.acquire() 1677 results = self.__test_results 1678 self.__lock.release() 1679 return results
1680 1681
1682 - def GetTestResultsInOrder(self):
1683 """Return the test results in the order they appeared. 1684 1685 returns -- A sequence of test results, in the order that they 1686 appeared.""" 1687 1688 self.__lock.acquire() 1689 results = self.__test_results_in_order 1690 self.__lock.release() 1691 return results
1692 1693
1694 - def GetResourceResults(self):
1695 """Return the accumulated resource results. 1696 1697 returns -- A dictionary mapping resource names to 'Result' 1698 objects.""" 1699 1700 self.__lock.acquire() 1701 results = self.__resource_results 1702 self.__lock.release() 1703 return results
1704 1705
1706 - def GetResult(self, name):
1707 """Return the 'Result' with the indicated 'name'. 1708 1709 'name' -- A string giving the name of a test or resource result. 1710 1711 returns -- The 'Result' instance corresponding to 'name'.""" 1712 1713 self.__lock.acquire() 1714 result = self.__test_results.get(name) 1715 if not result: 1716 result = self.__resource_results.get(name) 1717 self.__lock.release() 1718 1719 return result
1720 1721
1722 -class TestResultsPage(QMTestPage):
1723 """DTML page for displaying test results.""" 1724
1725 - def __init__(self, server):
1726 """Construct a new 'TestResultsPage'. 1727 1728 'server' -- The 'QMTestServer' creating this page.""" 1729 1730 # Initialize the base classes. 1731 QMTestPage.__init__(self, "results.dtml", server) 1732 1733 results_stream = server.GetResultsStream() 1734 # It is important that we ask for IsFinished before asking 1735 # for GetTestResults. The stream could be finished between 1736 # the two calls, and it is better to show all the results but 1737 # claim they are incomplete than to show only some of the 1738 # results and claim they are complete. 1739 self.__is_finished = results_stream.IsFinished() 1740 self.test_results = results_stream.GetTestResultsInOrder() 1741 self.expected_outcomes = server.GetExpectedOutcomes()
1742 1743
1744 - def GetOutcomes(self):
1745 """Return the list of result outcomes. 1746 1747 returns -- A sequence of result outcomes.""" 1748 1749 return Result.outcomes
1750 1751
1752 - def GetTotal(self):
1753 """Return the total number of tests. 1754 1755 returns -- The total number of tests.""" 1756 1757 return len(self.test_results)
1758 1759
1760 - def GetTotalUnexpected(self):
1761 """Return the total number of unexpected results. 1762 1763 returns -- The total number of unexpected results.""" 1764 1765 return len(self.GetRelativeResults(self.test_results, 0))
1766 1767
1768 - def GetResultsWithOutcome(self, outcome):
1769 """Return the number of tests with the given 'outcome'. 1770 1771 'outcome' -- One of the 'Result.outcomes'. 1772 1773 returns -- The results with the given 'outcome'.""" 1774 1775 return filter(lambda r, o=outcome: r.GetOutcome() == o, 1776 self.test_results)
1777 1778
1779 - def GetCount(self, outcome):
1780 """Return the number of tests with the given 'outcome'. 1781 1782 'outcome' -- One of the 'Result.outcomes'. 1783 1784 returns -- The number of tests with the given 'outcome'.""" 1785 1786 return len(self.GetResultsWithOutcome(outcome))
1787 1788
1789 - def GetUnexpectedCount(self, outcome):
1790 """Return the number of tests with the given 'outcome'. 1791 1792 'outcome' -- One of the 'Result.outcomes'. 1793 1794 returns -- The number of tests with the given 'outcome' that 1795 were expected to have some other outcome.""" 1796 1797 results = self.GetResultsWithOutcome(outcome) 1798 results = self.GetRelativeResults(results, 0) 1799 return len(results)
1800 1801
1802 - def GetRelativeResults(self, results, expected):
1803 """Return the results that match, or fail to match, expectations. 1804 1805 'results' -- A sequence of 'Result' objects. 1806 1807 'expected' -- A boolean. If true, expected results are 1808 returned. If false, unexpected results are returned.""" 1809 1810 if expected: 1811 return filter(lambda r, er=self.expected_outcomes: \ 1812 r.GetOutcome() == er.get(r.GetId(), 1813 Result.PASS), 1814 results) 1815 else: 1816 return filter(lambda r, er=self.expected_outcomes: \ 1817 r.GetOutcome() != er.get(r.GetId(), 1818 Result.PASS), 1819 results)
1820 1821
1822 - def GetDetailUrl(self, test_id):
1823 """Return the detail URL for a test. 1824 1825 'test_id' -- The name of the test. 1826 1827 returns -- The URL that contains details about the 'test_id'.""" 1828 1829 return qm.web.WebRequest("show-result", 1830 base=self.request, 1831 id=test_id).AsUrl()
1832 1833
1834 - def IsFinished(self):
1835 """Return true iff no more results are forthcoming. 1836 1837 returns -- True if no more tests are running.""" 1838 1839 return self.__is_finished
1840 1841
1842 - def GetRefreshDelay(self):
1843 """Returns the number of seconds to wait before refreshing the page. 1844 1845 returns -- The number of seconds to wait before refreshing this 1846 page. A value of zero means that te page should never be 1847 refreshed. This function is only called if 'IsFinished' returns 1848 true.""" 1849 1850 return 10
1851 1852 1853
1854 -class QMTestServer(qm.web.WebServer):
1855 """A 'QMTestServer' is the web GUI interface to QMTest.""" 1856
1857 - def __init__(self, database, port, address, log_file, 1858 targets, context, expectations, 1859 run_db):
1860 """Create and bind an HTTP server. 1861 1862 'database' -- The test database to serve. 1863 1864 'port' -- The port number on which to accept HTTP requests. 1865 1866 'address' -- The local address to which to bind the server. An 1867 empty string indicates all local addresses. 1868 1869 'log_file' -- A file object to which the server will log requests. 1870 'None' for no logging. 1871 1872 'targets' -- A sequence of 'Target' objects to use when running 1873 tests. 1874 1875 'context' -- The 'Context' in which tests will execute.""" 1876 1877 qm.web.WebServer.__init__(self, port, address, log_file=log_file) 1878 1879 self.__database = database 1880 self.__targets = targets 1881 self.__context = context 1882 1883 # Register all our web pages. 1884 for name, function in [ 1885 ( "/test/clear-results", self.HandleClearResults ), 1886 ( "/test/create-resource", self.HandleShowItem ), 1887 ( "/test/create-suite", self.HandleCreateSuite ), 1888 ( "/test/create-test", self.HandleShowItem ), 1889 ( "/test/delete-resource", self.HandleDeleteItem ), 1890 ( "/test/delete-suite", self.HandleDeleteSuite ), 1891 ( "/test/delete-test", self.HandleDeleteItem ), 1892 ( "/test/dir", self.HandleDir ), 1893 ( "/test/edit-context", self.HandleEditContext ), 1894 ( "/test/edit-resource", self.HandleShowItem ), 1895 ( "/test/edit-suite", self.HandleEditSuite ), 1896 ( "/test/edit-test", self.HandleShowItem ), 1897 ( "/test/load-context", self.HandleLoadContext ), 1898 ( "/test/load-expectations", self.HandleLoadExpectations ), 1899 ( "/test/load-results", self.HandleLoadResults ), 1900 ( "/test/new-resource", self.HandleNewResource ), 1901 ( "/test/new-suite", self.HandleNewSuite ), 1902 ( "/test/new-test", self.HandleNewTest ), 1903 ( "/test/run-tests", self.HandleRunTests ), 1904 ( "/test/set-expectation", self.HandleSetExpectation ), 1905 ( "/test/show-dir", self.HandleDir ), 1906 ( "/test/show-resource", self.HandleShowItem ), 1907 ( "/test/show-result", self.HandleShowResult ), 1908 ( "/test/show-results", self.HandleShowResults ), 1909 ( "/test/show-suite", self.HandleShowSuite ), 1910 ( "/test/show-test", self.HandleShowItem ), 1911 ( "/test/shutdown", self.HandleShutdown ), 1912 ( "/test/stop-tests", self.HandleStopTests ), 1913 ( "/test/submit-context", self.HandleSubmitContext ), 1914 ( "/test/submit-context-file", self.HandleSubmitContextFile ), 1915 ( "/test/submit-expectation", self.HandleSubmitExpectation ), 1916 ( "/test/submit-resource", self.HandleSubmitItem ), 1917 ( "/test/submit-expectations", self.HandleSubmitExpectations ), 1918 ( "/test/submit-expectations-form", self.HandleSubmitExpectationsForm ), 1919 ( "/test/submit-results", self.HandleSubmitResults ), 1920 ( "/test/submit-suite", self.HandleSubmitSuite ), 1921 ( "/test/submit-test", self.HandleSubmitItem ), 1922 ( "/test/" + qm.test.cmdline.QMTest.context_file_name, 1923 self.HandleSaveContext ), 1924 ( "/test/" + qm.test.cmdline.QMTest.expectations_file_name, 1925 self.HandleSaveExpectations ), 1926 ( "/test/" + qm.test.cmdline.QMTest.results_file_name, 1927 self.HandleSaveResults ), 1928 ( "/report/dir", self.HandleDirReport ), 1929 ( "/report/show-dir", self.HandleDirReport ), 1930 ( "/report/show-test", self.HandleShowItemReport ), 1931 ( "/report/show-resource", self.HandleShowItemReport ), 1932 ( "/report/show-result", self.HandleShowResultReport ), 1933 ( "/report/show-result", self.HandleShowResult ), 1934 ]: 1935 self.RegisterScript(name, function) 1936 1937 1938 self.RegisterPathTranslation( 1939 "/stylesheets", qm.get_share_directory("web", "stylesheets")) 1940 self.RegisterPathTranslation( 1941 "/images", qm.get_share_directory("web", "images")) 1942 self.RegisterPathTranslation( 1943 "/static", qm.get_share_directory("web", "static")) 1944 # Register the QM manual. 1945 self.RegisterPathTranslation( 1946 "/tutorial", qm.get_doc_directory("html", "tutorial")) 1947 1948 # The DB's attachment store processes download requests for 1949 # attachment data. 1950 attachment_store = database.GetAttachmentStore() 1951 if attachment_store: 1952 self.RegisterScript(qm.fields.AttachmentField.download_url, 1953 attachment_store.HandleDownloadRequest) 1954 1955 self.__expectation_db = expectations 1956 self.__expected_outcomes = {} 1957 for test_id in self.__database.GetTestIds(): 1958 result = expectations.Lookup(test_id) 1959 self.__expected_outcomes[test_id] = result.GetOutcome() 1960 self.__run_db = run_db 1961 # There are no results yet. 1962 self.__results_stream = StorageResultsStream() 1963 self.__results_stream.Summarize() 1964 # There is no execution thread. 1965 self.__execution_thread = None 1966 1967 # Bind the server to the specified address. 1968 try: 1969 self.Bind() 1970 except qm.web.AddressInUseError, address: 1971 raise RuntimeError, qm.error("address in use", address=address) 1972 except qm.web.PrivilegedPortError: 1973 raise RuntimeError, qm.error("privileged port", port=port)
1974 1975
1976 - def GetContext(self):
1977 """Return the 'Context' in which tests will be run. 1978 1979 returns -- The 'Context' in which tests will be run.""" 1980 1981 return self.__context
1982 1983
1984 - def GetDatabase(self):
1985 """Return the 'Database' handled by this server. 1986 1987 returns -- The 'Database' handled by this server.""" 1988 1989 return self.__database
1990 1991
1992 - def GetRunDatabase(self):
1993 """Return the 'RunDatabase' handled by this server. 1994 1995 returns -- The 'RunDatabase' handled by this server.""" 1996 1997 return self.__run_db
1998 1999
2000 - def GetExpectationDatabase(self):
2001 """Return the current ExpectationDatabase. 2002 2003 returns -- The ExpectationDatabase instance.""" 2004 2005 return self.__expectation_db
2006 2007
2008 - def GetExpectedOutcomes(self):
2009 """Return the current expected outcomes for the test database. 2010 2011 returns -- A map from test IDs to outcomes. Some tests may have 2012 not have an entry in the map.""" 2013 2014 return self.__expected_outcomes
2015 2016
2017 - def GetHTMLClassForOutcome(self, outcome):
2018 """Return the CSS class for the 'outcome'. 2019 2020 'outcome' -- One of the result outcomes. 2021 2022 returns -- The name of a CSS class. These are used with <span> 2023 elements. See 'qm.css'.""" 2024 2025 return { 2026 Result.PASS: "qmtest_pass", 2027 Result.FAIL: "qmtest_fail", 2028 Result.UNTESTED: "qmtest_untested", 2029 Result.ERROR: "qmtest_error", 2030 "EXPECTED" : "qmtest_expected" 2031 }[outcome]
2032 2033
2034 - def GetResultsStream(self):
2035 """Return the 'StorageResultsStream' containing test results. 2036 2037 returns -- The 'StorageResultsStream' associated with this 2038 server.""" 2039 2040 return self.__results_stream
2041 2042
2043 - def HandleClearResults(self, request):
2044 """Handle a request to clear the current test results. 2045 2046 'request' -- A 'WebRequest' object.""" 2047 2048 # Eliminate the old results stream. 2049 del self.__results_stream 2050 # And create a new one. 2051 self.__results_stream = StorageResultsStream() 2052 self.__results_stream.Summarize() 2053 2054 # Redirect to the main page. 2055 request = qm.web.WebRequest("dir", base=request) 2056 raise qm.web.HttpRedirect, request
2057 2058
2059 - def HandleCreateSuite(self, request):
2060 """Handle a submission of a new test suite. 2061 2062 'request' -- A 'WebRequest' object.""" 2063 2064 field_errors = {} 2065 database = self.__database 2066 2067 # Extract the suite ID of the new suite from the request. 2068 suite_id = request["id"] 2069 # Check that the ID is valid. 2070 if not database.IsValidLabel(suite_id, is_component = 0): 2071 field_errors["_id"] = qm.error("invalid id", id=suite_id) 2072 # Check that the ID doesn't already exist. 2073 elif database.HasSuite(suite_id): 2074 field_errors["_id"] = qm.error("suite already exists", 2075 suite_id=suite_id) 2076 2077 # Were there any validation errors? 2078 if len(field_errors) > 0: 2079 # Yes. Instead of showing the page for editing the suite, 2080 # redisplay the new suite page with error messages. 2081 return NewSuitePage(self, suite_id, field_errors)(request) 2082 else: 2083 # Everything looks good. Make an empty suite. 2084 suite_class = qm.test.base.get_extension_class( 2085 "explicit_suite.ExplicitSuite", 2086 "suite", 2087 self.GetDatabase()) 2088 extras = { suite_class.EXTRA_DATABASE : self.GetDatabase(), 2089 suite_class.EXTRA_ID : suite_id } 2090 suite = suite_class({}, **extras) 2091 # Show the editing page. 2092 return ShowSuitePage(self, suite, edit=1, is_new_suite=1)(request)
2093 2094
2095 - def HandleDeleteItem(self, request):
2096 """Handle a request to delete a test or resource. 2097 2098 This function handles the script requests 'delete-test' and 2099 'delete-resource'. 2100 2101 'request' -- A 'WebRequest' object. 2102 2103 The ID of the test or resource to delete is specified in the 'id' 2104 field of the request.""" 2105 2106 database = self.__database 2107 # Extract the item ID. 2108 item_id = request["id"] 2109 # The script name determines whether we're deleting a test or an 2110 # resource. 2111 script_name = request.GetScriptName() 2112 if script_name == "delete-test": 2113 database.RemoveExtension(item_id, database.TEST) 2114 elif script_name == "delete-resource": 2115 database.RemoveExtension(item_id, database.RESOURCE) 2116 else: 2117 raise RuntimeError, "unrecognized script name" 2118 # Redirect to the main page. 2119 request = qm.web.WebRequest("dir", base=request) 2120 raise qm.web.HttpRedirect, request
2121 2122
2123 - def HandleDeleteSuite(self, request):
2124 """Handle a request to delete a test suite. 2125 2126 'request' -- A 'WebRequest' object. 2127 2128 The ID of the suite to delete is specified in the 'id' field of the 2129 request.""" 2130 2131 database = self.__database 2132 # Extract the suite ID. 2133 suite_id = request["id"] 2134 database.RemoveExtension(suite_id, database.SUITE) 2135 # Redirect to the main page. 2136 raise qm.web.HttpRedirect, qm.web.WebRequest("dir", base=request)
2137 2138
2139 - def HandleDir(self, request):
2140 """Generate a directory page. 2141 2142 'request' -- A 'WebRequest' object. 2143 2144 The request has these fields: 2145 2146 'path' -- A path in test/resource/suite ID space. If specified, 2147 only tests and resources in this subtree are displayed, and their 2148 IDs are displayed relative to this path. If omitted, the entire 2149 contents of the test database are shown.""" 2150 2151 path = request.get("id", "") 2152 return DirPage(self, path)(request)
2153 2154
2155 - def HandleDirReport(self, request):
2156 """Generate a directory report page. 2157 2158 'request' -- A 'WebRequest' object. 2159 2160 The request has these fields: 2161 2162 'path' -- A path in test/resource/suite ID space. If specified, 2163 only tests and resources in this subtree are displayed, and their 2164 IDs are displayed relative to this path. If omitted, the entire 2165 contents of the test database are shown.""" 2166 2167 path = request.get("id", "") 2168 return DirReportPage(self, path)(request)
2169 2170
2171 - def HandleEditContext(self, request):
2172 """Handle a request to edit the context. 2173 2174 'request' -- The 'WebRequest' that caused the event.""" 2175 2176 context_page = ContextPage(self) 2177 return context_page(request)
2178 2179
2180 - def HandleEditSuite(self, request):
2181 """Generate the page for editing a test suite.""" 2182 2183 return self.HandleShowSuite(request, edit=1)
2184 2185
2186 - def HandleLoadContext(self, request):
2187 """Handle a request to upload a context file. 2188 2189 'request' -- The 'WebRequest' that caused the event.""" 2190 2191 return LoadContextPage(self)(request)
2192 2193
2194 - def HandleLoadExpectations(self, request):
2195 """Handle a request to upload results. 2196 2197 'request' -- The 'WebRequest' that caused the event.""" 2198 2199 return LoadExpectationsPage(self)(request)
2200 2201
2202 - def HandleLoadResults(self, request):
2203 """Handle a request to upload results. 2204 2205 'request' -- The 'WebRequest' that caused the event.""" 2206 2207 return LoadResultsPage(self)(request)
2208 2209
2210 - def HandleNewResource(self, request):
2211 """Handle a request to create a new test. 2212 2213 'request' -- The 'WebRequest' that caused the event.""" 2214 2215 return NewItemPage(self, "resource")(request)
2216 2217
2218 - def HandleNewTest(self, request):
2219 """Handle a request to create a new test. 2220 2221 'request' -- The 'WebRequest' that caused the event.""" 2222 2223 return NewItemPage(self, "test")(request)
2224 2225
2226 - def HandleNewSuite(self, request):
2227 """Handle a request to create a new suite. 2228 2229 'request' -- The 'WebRequest' that caused the event.""" 2230 2231 return NewSuitePage(self)(request)
2232 2233
2234 - def HandleRunTests(self, request):
2235 """Handle a request to run tests. 2236 2237 'request' -- The 'WebRequest' that caused the event. 2238 2239 These fields in 'request' are used: 2240 2241 'ids' -- A comma-separated list of test and suite IDs. These IDs 2242 are expanded into the list of IDs of tests to run. 2243 2244 """ 2245 2246 # Extract and expand the IDs of tests to run. 2247 if request.has_key("ids"): 2248 ids = string.split(request["ids"], ",") 2249 # '.' is an alias for <all>, and thus shadows other selectors. 2250 if '.' in ids: 2251 ids = [""] 2252 else: 2253 ids = [""] 2254 test_ids = self.GetDatabase().ExpandIds(ids)[0] 2255 2256 # Let the results stream know that we are going to start 2257 # providing it with results. 2258 self.__results_stream.Start(test_ids) 2259 2260 # Create the thread that will run all of the tests. 2261 del self.__execution_thread 2262 test_ids.sort() 2263 self.__execution_thread = \ 2264 ExecutionThread(self.__database, test_ids, self.__context, 2265 self.__targets, [self.__results_stream], 2266 self.__expectation_db) 2267 # Start the thread. 2268 self.__execution_thread.start() 2269 2270 # Sleep for a few seconds so that if we're only running one 2271 # test there's a good chance that it will finish before we 2272 # show the results page. 2273 time.sleep(5) 2274 2275 # Redirect to the results page. 2276 request = qm.web.WebRequest("show-results", base=request) 2277 raise qm.web.HttpRedirect, request
2278 2279
2280 - def HandleSaveContext(self, request):
2281 """Handlea request to save the context to a file. 2282 2283 'request' -- The 'WebRequest' that caused the event.""" 2284 2285 # Start with the empty string. 2286 s = "" 2287 # Run through all of the context variables. 2288 for (name, value) in self.__context.items(): 2289 s = s + "%s=%s\n" % (name, value) 2290 2291 return ("application/x-qmtest-context", s)
2292 2293
2294 - def HandleSaveExpectations(self, request):
2295 """Handle a request to save expectations to a file. 2296 2297 'request' -- The 'WebRequest' that caused the event.""" 2298 2299 # Create a string stream to store the results. 2300 s = StringIO.StringIO() 2301 # Create a results stream for storing the results. 2302 rsc = qm.test.cmdline.get_qmtest().GetFileResultStreamClass() 2303 rs = rsc({ "file" : s }) 2304 # Write all the results. 2305 for (id, outcome) in self.__expected_outcomes.items(): 2306 r = Result(Result.TEST, id, outcome) 2307 rs.WriteResult(r) 2308 # Terminate the stream. 2309 rs.Summarize() 2310 # Extract the data. 2311 data = s.getvalue() 2312 # Close the stream. 2313 s.close() 2314 2315 return ("application/x-qmtest-results", data)
2316 2317
2318 - def HandleSaveResults(self, request):
2319 """Handle a request to save results to a file. 2320 2321 'request' -- The 'WebRequest' that caused the event.""" 2322 2323 # Create a string stream to store the results. 2324 s = StringIO.StringIO() 2325 # Create a results stream for storing the results. 2326 rsc = qm.test.cmdline.get_qmtest().GetFileResultStreamClass() 2327 rs = rsc({ "file" : s }) 2328 # Write all the annotations. 2329 rs.WriteAllAnnotations(self.__results_stream.GetAnnotations()) 2330 # Write all the results. 2331 for r in self.__results_stream.GetTestResults().values(): 2332 rs.WriteResult(r) 2333 for r in self.__results_stream.GetResourceResults().values(): 2334 rs.WriteResult(r) 2335 # Terminate the stream. 2336 rs.Summarize() 2337 # Extract the data. 2338 data = s.getvalue() 2339 # Close the stream. 2340 s.close() 2341 2342 return ("application/x-qmtest-results", data)
2343 2344
2345 - def HandleSetExpectation(self, request):
2346 """Handle a request to set expectations. 2347 2348 'request' -- A 'WebRequest' object.""" 2349 2350 return SetExpectationPage(self, request["id"])(request)
2351 2352
2353 - def HandleShowItem(self, request):
2354 """Handle a request to show a test or resource. 2355 2356 'request' -- A 'WebRequest' object. 2357 2358 This function generates pages to handle these requests: 2359 2360 'create-test' -- Generate a form for initial editing of a test 2361 about to be created, given its test ID and test class. 2362 2363 'create-resource' -- Likewise for an resource. 2364 2365 'show-test' -- Display a test. 2366 2367 'show-resource' -- Likewise for an resource. 2368 2369 'edit-test' -- Generate a form for editing an existing test. 2370 2371 'edit-resource' -- Likewise for an resource. 2372 2373 This function distinguishes among these cases by checking the script 2374 name of the request object. 2375 2376 The request must have the following fields: 2377 2378 'id' -- A test or resource ID. For show or edit pages, the ID of an 2379 existing item. For create pages, the ID of the item being 2380 created. 2381 2382 'class' -- For create pages, the name of the test or resource 2383 class. 2384 2385 """ 2386 2387 # Paramaterize this function based on the request's script name. 2388 url = request.GetScriptName() 2389 edit, create, type = { 2390 "show-test": (0, 0, "test"), 2391 "edit-test": (1, 0, "test"), 2392 "create-test": (1, 1, "test"), 2393 "show-resource": (0, 0, "resource"), 2394 "edit-resource": (1, 0, "resource"), 2395 "create-resource": (1, 1, "resource"), 2396 }[url] 2397 2398 database = self.__database 2399 2400 try: 2401 # Determine the ID of the item. 2402 item_id = request["id"] 2403 except KeyError: 2404 # The user probably submitted the form without entering an ID. 2405 message = qm.error("no id for show") 2406 return qm.web.generate_error_page(request, message) 2407 2408 if create: 2409 # We're in the middle of creating a new item. 2410 class_name = request["class"] 2411 2412 # First perform some validation. 2413 field_errors = {} 2414 # Check that the ID is valid. 2415 if not database.IsValidLabel(item_id, is_component = 0): 2416 field_errors["_id"] = qm.error("invalid id", id=item_id) 2417 else: 2418 # Check that the ID doesn't already exist. 2419 if type == "resource": 2420 if database.HasResource(item_id): 2421 field_errors["_id"] \ 2422 = qm.error("resource already exists", 2423 resource_id=item_id) 2424 elif type == "test": 2425 if database.HasTest(item_id): 2426 field_errors["_id"] = qm.error("test already exists", 2427 test_id=item_id) 2428 # Check that the class exists. 2429 try: 2430 qm.test.base.get_extension_class(class_name, type, 2431 database) 2432 except ValueError: 2433 # The class name was incorrectly specified. 2434 field_errors["_class"] = qm.error("invalid class name", 2435 class_name=class_name) 2436 except: 2437 # Can't find the class. 2438 field_errors["_class"] = qm.error("class not found", 2439 class_name=class_name) 2440 # Were there any errors? 2441 if len(field_errors) > 0: 2442 # Yes. Instead of showing the edit page, re-show the new 2443 # item page. 2444 page = NewItemPage(server=self, 2445 type=type, 2446 item_id=item_id, 2447 class_name=class_name, 2448 field_errors=field_errors) 2449 return page(request) 2450 2451 # Construct a test with default argument values, as the 2452 # starting point for editing. 2453 if type == "resource": 2454 item = self.MakeNewResource(class_name, item_id) 2455 elif type == "test": 2456 item = self.MakeNewTest(class_name, item_id) 2457 else: 2458 # We're showing or editing an existing item. 2459 # Look it up in the database. 2460 if type == "resource": 2461 try: 2462 item = database.GetResource(item_id) 2463 except qm.test.database.NoSuchTestError, e: 2464 # An test with the specified test ID was not fount. 2465 # Show a page indicating the error. 2466 return qm.web.generate_error_page(request, str(e)) 2467 elif type == "test": 2468 try: 2469 item = database.GetTest(item_id) 2470 except qm.test.database.NoSuchResourceError, e: 2471 # An test with the specified resource ID was not fount. 2472 # Show a page indicating the error. 2473 return qm.web.generate_error_page(request, str(e)) 2474 2475 # Generate HTML. 2476 return ShowItemPage(self, item, edit, create, type)(request)
2477 2478
2479 - def HandleShowResult(self, request):
2480 """Handle a request to show result detail. 2481 If a 'test_run' argument was provided, fetch the result from the 2482 corresponding test run. Else read it from the results stream. 2483 2484 'request' -- The 'WebRequest' that caused the event.""" 2485 2486 name = request["id"] 2487 test_run = request.get("test_run") 2488 if test_run: 2489 run_db = self.GetRunDatabase() 2490 result = run_db.GetAllRuns()[int(test_run)].GetResult(name) 2491 else: 2492 result = self.__results_stream.GetResult(name) 2493 return ResultPage(self, result)(request)
2494 2495
2496 - def HandleShowResults(self, request):
2497 """Handle a request to show results. 2498 2499 'request' -- The 'WebRequest' that caused the event.""" 2500 2501 # Display the results. 2502 results_page = TestResultsPage(self) 2503 return results_page(request)
2504 2505
2506 - def HandleShowItemReport(self, request):
2507 """Handle a request to show a test or resource report. 2508 2509 'request' -- A 'WebRequest' object. 2510 2511 This function generates pages to handle these requests: 2512 2513 'show-test' -- Display a test. 2514 2515 'show-resource' -- Likewise for an resource. 2516 2517 This function distinguishes among these cases by checking the script 2518 name of the request object. 2519 2520 The request must have the following fields: 2521 2522 'id' -- A test or resource ID. For show or edit pages, the ID of an 2523 existing item. For create pages, the ID of the item being 2524 created.""" 2525 2526 # Paramaterize this function based on the request's script name. 2527 url = request.GetScriptName() 2528 type = {"show-test": "test", 2529 "show-resource": "resource"}[url] 2530 2531 database = self.GetDatabase() 2532 2533 try: 2534 # Determine the ID of the item. 2535 item_id = request["id"] 2536 except KeyError: 2537 # The user probably submitted the form without entering an ID. 2538 message = qm.error("no id for show") 2539 return qm.web.generate_error_page(request, message) 2540 2541 if type == "resource": 2542 try: 2543 item = database.GetResource(item_id) 2544 except qm.test.database.NoSuchTestError, e: 2545 return qm.web.generate_error_page(request, str(e)) 2546 elif type == "test": 2547 try: 2548 item = database.GetTest(item_id) 2549 except qm.test.database.NoSuchResourceError, e: 2550 return qm.web.generate_error_page(request, str(e)) 2551 2552 # Generate HTML. 2553 return ShowItemReportPage(self, item, type)(request)
2554 2555
2556 - def HandleShowResultReport(self, request):
2557 """Handle a request to show result report. 2558 2559 'request' -- The 'WebRequest' that caused the event.""" 2560 2561 return xxx
2562 #name = request["id"] 2563 #result = self.__results_stream.GetResult(name) 2564 #return ResultPage(self, result)(request) 2565 2566
2567 - def HandleShowSuite(self, request, edit=0):
2568 """Generate the page for displaying or editing a test suite. 2569 2570 'request' -- A 'WebRequest' object. 2571 2572 'edit' -- If true, display the page for editing the suite. 2573 Otherwise, just display the suite. 2574 2575 The request has the following fields: 2576 2577 'id' -- The ID of the suite to display or edit.""" 2578 2579 database = self.__database 2580 2581 try: 2582 # Determine the suite ID. 2583 suite_id = request["id"] 2584 except KeyError: 2585 # No suite ID was given. 2586 message = qm.error("no id for show") 2587 return qm.web.generate_error_page(request, message) 2588 else: 2589 suite = database.GetSuite(suite_id) 2590 # Generate HTML. 2591 return ShowSuitePage(self, suite, edit, is_new_suite=0)(request)
2592 2593
2594 - def HandleShutdown(self, request):
2595 """Handle a request to shut down the server. 2596 2597 'request' -- The 'WebRequest' that caused the event.""" 2598 2599 raise SystemExit, None
2600 2601
2602 - def HandleStopTests(self, request):
2603 """Handle a request to stop test execution. 2604 2605 'request' -- The 'WebRequest' that caused the event.""" 2606 2607 # Stop the thread. 2608 self.__execution_thread.RequestTermination() 2609 # Redirect to the results page. 2610 request = qm.web.WebRequest("show-results", base=request) 2611 raise qm.web.HttpRedirect, request
2612 2613
2614 - def HandleSubmitContext(self, request):
2615 """Handle a context submission.. 2616 2617 'request' -- The 'WebRequest' that caused the event. The 2618 'request' must have a 'context_vars' key, whose value is the 2619 the context variables.""" 2620 2621 vars = qm.web.decode_properties(request["context_vars"]) 2622 self.__context = Context() 2623 for k in vars.keys(): 2624 self.__context[k] = vars[k] 2625 2626 # Redirect to the main page. 2627 request = qm.web.WebRequest("dir", base=request) 2628 raise qm.web.HttpRedirect, request
2629 2630
2631 - def HandleSubmitContextFile(self, request):
2632 """Handle a context file submission.. 2633 2634 'request' -- The 'WebRequest' that caused the event.""" 2635 2636 # The context data. 2637 data = request["file"] 2638 # Create a file objet to read from. 2639 file = StringIO.StringIO(data) 2640 # Parse the assignments in the context file. 2641 assignments = qm.common.read_assignments(file) 2642 # Add them to the context. 2643 for (name, value) in assignments.items(): 2644 try: 2645 self.__context[name] = value 2646 except ValueError: 2647 # Skip any invalid assignments. 2648 pass 2649 # Redirect to the main page. 2650 return self._ClosePopupAndRedirect("dir")
2651 2652
2653 - def HandleSubmitExpectation(self, request):
2654 """Handle setting a single expectation. 2655 2656 'request' -- The 'WebRequest' that caused the event.""" 2657 2658 id = request["id"] 2659 outcome = request["outcome"] 2660 self.__expected_outcomes[id] = outcome 2661 # Close the upload popup window, and reload the main window. 2662 return self._ClosePopupAndRedirect(request["url"])
2663 2664
2665 - def HandleSubmitExpectations(self, request):
2666 """Handle uploading expected results. 2667 2668 'request' -- The 'WebRequest' that caused the event.""" 2669 2670 # Get the results file data. 2671 data = request["file"] 2672 # Create a file object from the data. 2673 f = StringIO.StringIO(data) 2674 # Read the results. 2675 self.__expectation_db = \ 2676 qm.test.base.load_expectations(f, self.GetDatabase()) 2677 self.__expected_outcomes = {} 2678 for test_id in self.GetDatabase().GetTestIds(): 2679 expectation = self.__expectation_db.Lookup(test_id) 2680 self.__expected_outcomes[test_id] = expectation.GetOutcome() 2681 # Close the upload popup window, and redirect the main window 2682 # to the root of the database. 2683 return self._ClosePopupAndRedirect("dir")
2684 2685
2686 - def HandleSubmitExpectationsForm(self, request):
2687 """Handle uploading expected results. 2688 2689 'request' -- The 'WebRequest' that caused the event.""" 2690 2691 # Clear out the current set of expected outcomes; the entire 2692 # set of new 2693 self.__expected_outcomes = {} 2694 2695 # Loop over all the tests. 2696 for id in self.GetDatabase().ExpandIds("")[0]: 2697 outcome = request[id] 2698 if outcome != "None": 2699 self.__expected_outcomes[id] = outcome 2700 2701 # Redirect to the main page. 2702 request = qm.web.WebRequest("dir", base=request) 2703 raise qm.web.HttpRedirect, request
2704 2705
2706 - def HandleSubmitItem(self, request):
2707 """Handle a test or resource submission. 2708 2709 This function handles submission of the test or resource editing form 2710 generated by 'handle_show'. The script name in 'request' should be 2711 'submit-test' or 'submit-resource'. It constructs the appropriate 2712 'Test' or 'Resource' object and writes it to the database, either as a 2713 new item or overwriting an existing item. 2714 2715 The request must have the following form fields: 2716 2717 'id' -- The test or resource ID of the item being edited or created. 2718 2719 'class' -- The name of the test or resource class of this item. 2720 2721 arguments -- Argument values are encoded in fields whose names start 2722 with 'qm.fields.Field.form_field_prefix'.""" 2723 2724 if request.GetScriptName() == "submit-test": 2725 type = "test" 2726 elif request.GetScriptName() == "submit-resource": 2727 type = "resource" 2728 2729 # Make sure there's an ID in the request, and extract it. 2730 try: 2731 item_id = request["id"] 2732 except KeyError: 2733 message = qm.error("no id for submit") 2734 return qm.web.generate_error_page(request, message) 2735 2736 database = self.__database 2737 # Learn whether or not this is a new item. 2738 is_new = int(request["is_new"]) 2739 # Extract the class and field specification. 2740 item_class_name = request["class"] 2741 item_class = qm.test.base.get_extension_class(item_class_name, 2742 type, 2743 database) 2744 fields = get_class_arguments(item_class) 2745 2746 # We'll perform various kinds of validation as we extract form 2747 # fields. Errors are placed into this map. 2748 field_errors = {} 2749 redisplay = 0 2750 2751 # Loop over fields of the class, looking for arguments in the 2752 # submitted request. 2753 arguments = {} 2754 temporary_store = self.GetTemporaryAttachmentStore() 2755 main_store = database.GetAttachmentStore() 2756 attachment_stores = { id(temporary_store): temporary_store, 2757 id(main_store): main_store } 2758 for field in fields: 2759 # Construct the name we expect for the corresponding argument. 2760 field_name = field.GetName() 2761 form_field_name = field.GetHtmlFormFieldName() 2762 # Parse the value for this field. 2763 try: 2764 value, r = field.ParseFormValue(request, form_field_name, 2765 attachment_stores) 2766 if r: 2767 redisplay = 1 2768 arguments[field_name] = value 2769 except: 2770 # Something went wrong parsing the value. Associate an 2771 # error message with this field. 2772 message = str(sys.exc_info()[1]) 2773 field_errors[field_name] = message 2774 redisplay = 1 2775 2776 if type == "test": 2777 # Create a new test. 2778 item = TestDescriptor( 2779 database, 2780 test_id=item_id, 2781 test_class_name=item_class_name, 2782 arguments=arguments) 2783 2784 elif type == "resource": 2785 # Create a new resource. 2786 item = ResourceDescriptor(database, item_id, 2787 item_class_name, arguments) 2788 2789 # If necessary, redisplay the form. 2790 if redisplay: 2791 request = qm.web.WebRequest("edit-" + type, base=request, 2792 id=item_id) 2793 return ShowItemPage(self, item, 1, is_new, type, 2794 field_errors)(request) 2795 2796 # Store it in the database. 2797 database.WriteExtension(item_id, item.GetItem()) 2798 2799 # Redirect to a page that displays the newly-edited item. 2800 request = qm.web.WebRequest("show-" + type, base=request, id=item_id) 2801 raise qm.web.HttpRedirect, request
2802 2803
2804 - def HandleSubmitResults(self, request):
2805 """Handle uploading results. 2806 2807 'request' -- The 'WebRequest' that caused the event.""" 2808 2809 # Get the results file data. 2810 data = request["file"] 2811 # Create a file object from the data. 2812 f = StringIO.StringIO(data) 2813 # Read the results. 2814 results = qm.test.base.load_results(f, self.GetDatabase()) 2815 # Enter them into a new results stream. 2816 self.__results_stream = StorageResultsStream() 2817 annotations = results.GetAnnotations() 2818 self.__results_stream.WriteAllAnnotations(annotations) 2819 for r in results: 2820 self.__results_stream.WriteResult(r) 2821 self.__results_stream.Summarize() 2822 # Close the upload popup window, and redirect the main window 2823 # to a view of the results. 2824 return self._ClosePopupAndRedirect("show-results")
2825 2826
2827 - def HandleSubmitSuite(self, request):
2828 """Handle test suite submission. 2829 2830 'request' -- A 'WebRequest' object. 2831 2832 The request object has these fields: 2833 2834 'id' -- The ID of the test suite being edited. If a suite with 2835 this ID exists, it is replaced (it must not be an implicit suite 2836 though). Otherwise a new suite is edited. 2837 2838 'test_ids' -- A comma-separated list of test IDs to include in the 2839 suite, relative to the suite's own ID. 2840 2841 'suite_ids' -- A comma-separated list of other test suite IDs to 2842 include in the suite, relative to the suite's own ID. 2843 """ 2844 2845 database = self.__database 2846 # Extract fields from the request. 2847 suite_id = request["id"] 2848 test_ids = request["test_ids"] 2849 if string.strip(test_ids) == "": 2850 test_ids = [] 2851 else: 2852 test_ids = string.split(test_ids, ",") 2853 suite_ids = request["suite_ids"] 2854 if string.strip(suite_ids) == "": 2855 suite_ids = [] 2856 else: 2857 suite_ids = string.split(suite_ids, ",") 2858 # Construct a new suite. 2859 suite_class = qm.test.base.get_extension_class( 2860 "explicit_suite.ExplicitSuite", 2861 "suite", 2862 self.GetDatabase()) 2863 extras = { suite_class.EXTRA_DATABASE : self.GetDatabase(), 2864 suite_class.EXTRA_ID : suite_id } 2865 suite = suite_class({ "test_ids" : test_ids, 2866 "suite_ids" : suite_ids }, 2867 **extras) 2868 # Store it. 2869 database.WriteExtension(suite_id, suite) 2870 # Redirect to a page that displays the newly-edited item. 2871 raise qm.web.HttpRedirect, \ 2872 qm.web.WebRequest("show-suite", base=request, id=suite_id)
2873 2874
2875 - def MakeNewTest(self, test_class_name, test_id):
2876 """Create a new test with default arguments. 2877 2878 'test_class_name' -- The name of the test class of which to create a 2879 new test. 2880 2881 'test_id' -- The test ID of the new test. 2882 2883 returns -- A new 'TestDescriptor' object.""" 2884 2885 test_class = qm.test.base.get_test_class(test_class_name, 2886 self.GetDatabase()) 2887 # Make sure there isn't already such a test. 2888 if self.GetDatabase().HasTest(test_id): 2889 raise RuntimeError, qm.error("test already exists", 2890 test_id=test_id) 2891 # Construct an argument map containing default values. 2892 arguments = {} 2893 for field in get_class_arguments(test_class): 2894 name = field.GetName() 2895 value = field.GetDefaultValue() 2896 arguments[name] = value 2897 # Construct a default test instance. 2898 return TestDescriptor(self.GetDatabase(), test_id, 2899 test_class_name, arguments)
2900 2901
2902 - def MakeNewResource(self, resource_class_name, resource_id):
2903 """Create a new resource with default arguments. 2904 2905 'resource_class_name' -- The name of the resource class of which to 2906 create a new resource. 2907 2908 'resource_id' -- The resource ID of the new resource. 2909 2910 returns -- A new 'ResourceDescriptor' object.""" 2911 2912 resource_class \ 2913 = qm.test.base.get_resource_class(resource_class_name, 2914 self.GetDatabase()) 2915 # Make sure there isn't already such a resource. 2916 if self.GetDatabase().HasResource(resource_id): 2917 raise RuntimeError, qm.error("resource already exists", 2918 resource_id=resource_id) 2919 # Construct an argument map containing default values. 2920 arguments = {} 2921 for field in get_class_arguments(resource_class): 2922 name = field.GetName() 2923 value = field.GetDefaultValue() 2924 arguments[name] = value 2925 # Construct a default resource instance. 2926 return ResourceDescriptor(self.GetDatabase(), resource_id, 2927 resource_class_name, arguments)
2928 2929
2930 - def _HandleRoot(self, request):
2931 """Handle the '/' URL.""" 2932 2933 raise qm.web.HttpRedirect, qm.web.WebRequest("/test/dir")
2934 2935
2936 - def _ClosePopupAndRedirect(self, url):
2937 """Close the current window. Redirect the main window to 'url'. 2938 2939 'url' -- A string giving the URL to which the main window should 2940 be redirected. 2941 2942 returns -- A string giving HTML that will close the current 2943 window and redirect the main window to 'url'.""" 2944 2945 return """<html><body><script language="JavaScript"> 2946 window.opener.location = '%s'; 2947 window.close();</script></body></html>""" % url
2948 2949 ######################################################################## 2950 # initialization 2951 ######################################################################## 2952 2953 # Use our 'DefaultDtmlPage' subclass even when generating generic 2954 # (non-QMTest) pages. 2955 #qm.web.DtmlPage.default_class = DefaultDtmlPage 2956 2957 ######################################################################## 2958 # Local Variables: 2959 # mode: python 2960 # indent-tabs-mode: nil 2961 # fill-column: 72 2962 # End: 2963

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_Let-module.html0000664000076400007640000000235611122067144031555 0ustar stefanstefan DT_Let

Module DT_Let


Classes

Let

Functions

parse_let_params

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_engine.ExecutionEngine-class.html0000664000076400007640000011251711122067150032001 0ustar stefanstefan qm.test.execution_engine.ExecutionEngine
Package qm :: Package test :: Module execution_engine :: Class ExecutionEngine
[hide private]
[frames] | no frames]

Class ExecutionEngine

source code

A 'ExecutionEngine' executes tests.

A 'ExecutionEngine' object handles the execution of a collection of tests.

This class schedules the tests across one or more targets.

The shedule is determined dynamically as the tests are executed based on which targets are idle and which are not. Therefore, the testing load should be reasonably well balanced, even across a heterogeneous network of testing machines.

Nested Classes [hide private]
  __TestStatus
A '__TestStatus' indicates whether or not a test has been run.
Instance Methods [hide private]
 
__init__(self, database, test_ids, context, targets, result_streams=None, expectations=None)
Set up a test run.
source code
 
RequestTermination(self)
Request that the execution engine stop executing tests.
source code
 
_IsTerminationRequested(self)
Returns true if termination has been requested.
source code
 
Run(self)
Run the tests.
source code
 
AddInputHandler(self, fd, function)
Add an input handler for 'fd'.
source code
 
_RunTests(self) source code
 
__FeedTarget(self, target)
Run a test on 'target'
source code
 
__FindRunnableTest(self, target)
Return a test that is ready to run.
source code
 
__AddTestToStack(self, test_id)
Adds 'test_id' to the stack of current tests.
source code
 
__AddToTargetPatternQueue(self, descriptor)
A a test to the appropriate target pattern queue.
source code
 
__GetPendingPrerequisites(self, descriptor)
Return pending prerequisite tests for 'descriptor'.
source code
 
__AddResult(self, result)
Report the result of running a test or resource.
source code
 
__CheckForResponse(self, wait)
See if any of the targets have completed a task.
source code
 
__AddUntestedResult(self, test_name, cause, annotations={}, exc_info=None)
Add a 'Result' indicating that 'test_name' was not run.
source code
 
__GetTestDescriptor(self, test_id)
Return the 'TestDescriptor' for 'test_id'.
source code
 
_Trace(self, message)
Write a trace 'message'.
source code
 
_WriteInitialAnnotations(self) source code
Class Variables [hide private]
  __TARGET_IDLE = "IDLE"
  __TARGET_BUSY = "BUSY"
  __TARGET_STARVING = "STARVING"
Method Details [hide private]

__init__(self, database, test_ids, context, targets, result_streams=None, expectations=None)
(Constructor)

source code 

Set up a test run.

'database' -- The 'Database' containing the tests that will be run.

'test_ids' -- A sequence of IDs of tests to run. Where possible, the tests are started in the order specified.

'context' -- The context object to use when running tests.

'targets' -- A sequence of 'Target' objects, representing targets on which tests may be run.

'result_streams' -- A sequence of 'ResultStream' objects. Each stream will be provided with results as they are available.

'expectations' -- If not 'None', an ExpectationDatabase object.

RequestTermination(self)

source code 

Request that the execution engine stop executing tests.

Request that the execution thread be terminated. Termination may take some time; tests that are already running will continue to run, for example.

_IsTerminationRequested(self)

source code 

Returns true if termination has been requested.

returns -- True if no further tests should be executed. If the value is -1, the execution engine should simply terminate gracefully.

Run(self)

source code 

Run the tests.

This method runs the tests specified in the __init__ function.

returns -- True if any tests had unexpected outcomes.

AddInputHandler(self, fd, function)

source code 

Add an input handler for 'fd'.

'fd' -- A file descriptor, open for reading.

'function' -- A callable object taking a single parameter.

The execution engine will periodically monitor 'fd'. When input is available, it will call 'function' passing it 'fd'.

__FeedTarget(self, target)

source code 

Run a test on 'target'

'target' -- The 'Target' on which the test should be run.

returns -- True, iff a test could be found to run on 'target'. False otherwise.

__FindRunnableTest(self, target)

source code 

Return a test that is ready to run.

'target' -- The 'Target' on which the test will run.

returns -- the 'TestDescriptor' for the next available ready test, or 'None' if no test could be found that will run on 'target'.

If a test with unsatisfied prerequisites is encountered, the test will be pushed on the stack and the prerequisites processed recursively.

__AddTestToStack(self, test_id)

source code 

Adds 'test_id' to the stack of current tests.

returns -- True if the test was added to the stack; false if the test could not be loaded. In the latter case, an 'UNTESTED' result is recorded for the test.

__AddToTargetPatternQueue(self, descriptor)

source code 

A a test to the appropriate target pattern queue.

'descriptor' -- A 'TestDescriptor'.

Adds the test to the target pattern queue indicated in the descriptor.

__GetPendingPrerequisites(self, descriptor)

source code 

Return pending prerequisite tests for 'descriptor'.

'descriptor' -- A 'TestDescriptor'.

returns -- A list of prerequisite test ids that have to complete, or 'None' if one of the prerequisites had an unexpected outcome.

__AddResult(self, result)

source code 

Report the result of running a test or resource.

'result' -- A 'Result' object representing the result of running a test or resource.

__CheckForResponse(self, wait)

source code 

See if any of the targets have completed a task.

'wait' -- If false, this function returns immediately if there is no available response. If 'wait' is true, this function continues to wait until a response is available.

returns -- True iff a response was received.

__AddUntestedResult(self, test_name, cause, annotations={}, exc_info=None)

source code 

Add a 'Result' indicating that 'test_name' was not run.

'test_name' -- The label for the test that could not be run.

'cause' -- A string explaining why the test could not be run.

'annotations' -- A map from strings to strings giving additional annotations for the result.

'exc_info' -- If this test could not be tested due to a thrown exception, 'exc_info' is the result of 'sys.exc_info()' when the exception was caught. 'None' otherwise.

__GetTestDescriptor(self, test_id)

source code 

Return the 'TestDescriptor' for 'test_id'.

returns -- The 'TestDescriptor' for 'test_id', or 'None' if the descriptor could not be loaded.

If the database cannot load the descriptor, an 'UNTESTED' result is recorded for 'test_id'.

_Trace(self, message)

source code 

Write a trace 'message'.

'message' -- A string to be output as a trace message.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.tet_stream-module.html0000664000076400007640000000212611122067144030124 0ustar stefanstefan tet_stream

Module tet_stream


Classes

TETStream

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.rsh_target-module.html0000664000076400007640000001126311122067145027337 0ustar stefanstefan qm.test.classes.rsh_target
Package qm :: Package test :: Package classes :: Module rsh_target
[hide private]
[frames] | no frames]

Module rsh_target

source code

Classes [hide private]
  RSHTarget
A target that runs tests via a remote shell invocation.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.compiler_test-module.html0000664000076400007640000000252111122067144030625 0ustar stefanstefan compiler_test

Module compiler_test


Classes

CompilationStep
CompilerBase
CompilerTest

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.reader_test_run-module.html0000664000076400007640000000214511122067144027507 0ustar stefanstefan reader_test_run

Module reader_test_run


Classes

ReaderTestRun

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.EnumerationField-class.html0000664000076400007640000004776511122067146027123 0ustar stefanstefan qm.fields.EnumerationField
qm :: fields :: EnumerationField :: Class EnumerationField
[hide private]
[frames] | no frames]

Class EnumerationField

source code

object --+            
         |            
     Field --+        
             |        
     TextField --+    
                 |    
       ChoiceField --+
                     |
                    EnumerationField
Known Subclasses:

A field that contains an enumeral value.

The enumeral value is selected from an enumerated set of values. An enumeral field uses the following properties:

enumeration -- A mapping from enumeral names to enumeral values. Names are converted to strings, and values are stored as integers.

ordered -- If non-zero, the enumerals are presented to the user ordered by value.

Instance Methods [hide private]
 
__init__(self, name='', default_value=None, enumerals=[], **properties)
Create an enumeration field.
source code
 
GetItems(self)
Return a sequence of enumerals.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
MakeDomNodeForValue(self, value, document)
Generate a DOM element node for a value of this field.
source code
 
GetValueFromDomNode(self, node, attachment_store)
Return a value for this field represented by DOM 'node'.
source code

Inherited from ChoiceField: FormatValueAsHtml, Validate

Inherited from TextField: FormatValueAsText, ParseFormValue, ParseTextValue

Inherited from Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', default_value=None, enumerals=[], **properties)
(Constructor)

source code 

Create an enumeration field.

'enumerals' -- A sequence of strings of available enumerals.

'default_value' -- The default value for this enumeration. If 'None', the first enumeral is used.

Overrides: object.__init__

GetItems(self)

source code 

Return a sequence of enumerals.

returns -- A sequence consisting of string enumerals objects, in the appropriate order.

Overrides: ChoiceField.GetItems

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: Field.GetHelp
(inherited documentation)

MakeDomNodeForValue(self, value, document)

source code 

Generate a DOM element node for a value of this field.

'value' -- The value to represent.

'document' -- The containing DOM document node.

Overrides: Field.MakeDomNodeForValue
(inherited documentation)

GetValueFromDomNode(self, node, attachment_store)

source code 

Return a value for this field represented by DOM 'node'.

This method does not validate the value for this particular instance; it only makes sure the node is well-formed, and returns a value of the correct Python type.

'node' -- The DOM node that is being evaluated.

'attachment_store' -- For attachments, the store that should be used.

If the 'node' is incorrectly formed, this method should raise an exception.

Overrides: Field.GetValueFromDomNode
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.temporary-pysrc.html0000664000076400007640000010073011122067152027066 0ustar stefanstefan qm.test.classes.temporary
Package qm :: Package test :: Package classes :: Module temporary
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.temporary

 1  ######################################################################## 
 2  # 
 3  # File:   temporary.py 
 4  # Author: Alex Samuel 
 5  # Date:   2001-04-06 
 6  # 
 7  # Contents: 
 8  #   Resource classes to manage temporary files and directories. 
 9  # 
10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # imports 
18  ######################################################################## 
19   
20  import os 
21  import qm.common 
22  import qm.fields 
23  from   qm.test.result import * 
24  from   qm.test.test import * 
25  from   qm.test.resource import * 
26  import qm.temporary_directory 
27   
28  ######################################################################## 
29  # classes 
30  ######################################################################## 
31   
32 -class TempDirectoryResource(Resource):
33 """Resource class to manage a temporary directory. 34 35 An instance of this resource creates a temporary directory during 36 setup, and deletes it during cleanup. The full path to the 37 directory is available to tests via a context property.""" 38 39 arguments = [ 40 qm.fields.TextField( 41 name="dir_path_property", 42 title="Directory Path Property Name", 43 description="The name of the context property which is " 44 "set to the path to the temporary directory.", 45 default_value="temp_dir_path" 46 ), 47 48 qm.fields.IntegerField( 49 name="delete_recursively", 50 title="Delete Directory Recursively", 51 description="""This field is obsolete All temporary 52 directories are removed recursively.""", 53 default_value=1, 54 ), 55 ] 56 57
58 - def SetUp(self, context, result):
59 60 # Generate a temporary file name. 61 self.__dir = qm.temporary_directory.TemporaryDirectory() 62 context[self.dir_path_property] = self.__dir.GetPath()
63 64
65 - def CleanUp(self, result):
66 67 del self.__dir
68 69 70 ######################################################################## 71 # Local Variables: 72 # mode: python 73 # indent-tabs-mode: nil 74 # fill-column: 72 75 # End: 76

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist-pysrc.html0000664000076400007640000000716511122067153023406 0ustar stefanstefan qm.dist
Package qm :: Package dist
[hide private]
[frames] | no frames]

Source Code for Package qm.dist

1   
2   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.BooleanField-class.html0000664000076400007640000003535611122067146026205 0ustar stefanstefan qm.fields.BooleanField
qm :: fields :: BooleanField :: Class BooleanField
[hide private]
[frames] | no frames]

Class BooleanField

source code

object --+                
         |                
     Field --+            
             |            
     TextField --+        
                 |        
       ChoiceField --+    
                     |    
      EnumerationField --+
                         |
                        BooleanField

A field containing a boolean value.

The enumeration contains two values: true and false.

Instance Methods [hide private]
 
__init__(self, name='', default_value=None, **properties)
Create an enumeration field.
source code
 
Validate(self, value)
Validate a field value.
source code

Inherited from EnumerationField: GetHelp, GetItems, GetValueFromDomNode, MakeDomNodeForValue

Inherited from ChoiceField: FormatValueAsHtml

Inherited from TextField: FormatValueAsText, ParseFormValue, ParseTextValue

Inherited from Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', default_value=None, **properties)
(Constructor)

source code 

Create an enumeration field.

'enumerals' -- A sequence of strings of available enumerals.

'default_value' -- The default value for this enumeration. If 'None', the first enumeral is used.

Overrides: object.__init__
(inherited documentation)

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

Overrides: Field.Validate
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dg_test.DGTest.DGException-class.html0000664000076400007640000001547611122067147031763 0ustar stefanstefan qm.test.classes.dg_test.DGTest.DGException
Package qm :: Package test :: Package classes :: Module dg_test :: Class DGTest :: Class DGException
[hide private]
[frames] | no frames]

Class DGException

source code

              object --+        
                       |        
exceptions.BaseException --+    
                           |    
        exceptions.Exception --+
                               |
                              DGTest.DGException

The exception class raised by 'DGTest'.

When a 'DGTest' method detects an error situation, it raises an exception of this type.

Instance Methods [hide private]

Inherited from exceptions.Exception: __init__, __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result_stream-pysrc.html0000664000076400007640000017413111122067152026307 0ustar stefanstefan qm.test.result_stream
Package qm :: Package test :: Module result_stream
[hide private]
[frames] | no frames]

Source Code for Module qm.test.result_stream

  1  ######################################################################## 
  2  # 
  3  # File:   result_stream.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2001-10-10 
  6  # 
  7  # Contents: 
  8  #   QMTest ResultStream class. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  import qm.extension 
 22  import qm.fields 
 23  from   qm.test.result import Result 
 24   
 25  ######################################################################## 
 26  # classes 
 27  ######################################################################## 
 28   
29 -class ResultStream(qm.extension.Extension):
30 """A 'ResultStream' displays test results. 31 32 A 'ResultStream' is responsible for displaying test results for 33 the user as they arrive. It may also display summary information 34 when the results are complete. The 'ResultStream' may also 35 choose to write the results to a file for permanent storage. 36 37 'ResultStream' is an abstract class. 38 39 """ 40 41 kind = "result_stream" 42 43 expected_outcomes = qm.fields.PythonField() 44 45
46 - def __init__(self, arguments = None, **args):
47 48 if arguments: args.update(arguments) 49 super(ResultStream, self).__init__(**args)
50 51
52 - def WriteAnnotation(self, key, value):
53 """Output an annotation for this run. 54 55 Subclasses should override this if they want to store/display 56 annotations; the default implementation simply discards them. 57 58 'key' -- the key value as a string. 59 60 'value' -- the value of this annotation as a string.""" 61 62 pass
63 64
65 - def WriteAllAnnotations(self, annotations):
66 """Output all annotations in 'annotations' to this stream. 67 68 Currently this is the same as making repeated calls to 69 'WriteAnnotation', but in the future, as special annotation 70 types like timestamps are added, this will do the work of 71 dispatching to functions like 'WriteTimestamp'. 72 73 Should not be overridden by subclasses.""" 74 75 for key, value in annotations.iteritems(): 76 self.WriteAnnotation(key, value)
77 78
79 - def WriteResult(self, result):
80 """Output a test result. 81 82 Subclasses must override this method; the default 83 implementation raises a 'NotImplementedError'. 84 85 'result' -- A 'Result'.""" 86 87 raise NotImplementedError
88 89
90 - def Summarize(self):
91 """Output summary information about the results. 92 93 When this method is called, the test run is complete. Summary 94 information should be displayed for the user, if appropriate. 95 Any finalization, such as the closing of open files, should 96 also be performed at this point. 97 98 Derived class methods may override this method. They should, 99 however, invoke this version before returning.""" 100 101 pass
102 103
104 - def _GetExpectedOutcome(self, test_id):
105 """Return the outcome expected for 'test_id'. 106 107 returns -- The outcome (one of the elements of 108 'Result.outcomes') expected for 'test_id'. The expected 109 outcome is taken from the 'expected_outcomes' provided when 110 constructing this result stream, if available. If no expected 111 outcome is available the default value ('Result.PASS') will be 112 returned.""" 113 114 return self.expected_outcomes.get(test_id, Result.PASS)
115

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external-module.html0000664000076400007640000000171111122067144025164 0ustar stefanstefan external

Module external



[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.explicit_suite-module.html0000664000076400007640000000215211122067144031006 0ustar stefanstefan explicit_suite

Module explicit_suite


Classes

ExplicitSuite

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.temporary_directory.TemporaryDirectory-class.html0000664000076400007640000002623611122067146032366 0ustar stefanstefan qm.temporary_directory.TemporaryDirectory
qm :: temporary_directory :: TemporaryDirectory :: Class TemporaryDirectory
[hide private]
[frames] | no frames]

Class TemporaryDirectory

source code

A 'TemporaryDirectory' is a directory for temporary files.

Creating a new 'TemporaryDirectory results in the creation of a new directory in the file system. The directory is automatically removed from the file system when the 'TemporaryDirectory' is destroyed.

Instance Methods [hide private]
 
__init__(self)
Construct a new 'TemporaryDirectory.
source code
 
GetPath(self)
Returns the path to the temporary directory.
source code
 
__del__(self) source code
 
Remove(self)
Remove the temporary directory.
source code
 
__RemoveDirectory(self, path)
Remove the directory 'path'.
source code
Method Details [hide private]

GetPath(self)

source code 

Returns the path to the temporary directory.

returns -- The path to the temporary directory.

Remove(self)

source code 

Remove the temporary directory.

Removes the temporary directory, and all files and directories contained within it, from the file system.

__RemoveDirectory(self, path)

source code 

Remove the directory 'path'.

Removes 'path', after first removing all of its contents.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.User-class.html0000664000076400007640000004115611122067151024277 0ustar stefanstefan qm.user.User
qm :: user :: User :: Class User
[hide private]
[frames] | no frames]

Class User

source code

A user account record.

User accounts contain three sets of properties.  Each property
is a name-value pair.  The three sets of properties are:

  informational properties -- General information about the
  user.  This may include the user's real name, contact
  information, etc.  These properties are generally
  user-visible, and should be modified only at the user's
  request.

  configuration properties -- Program-specific per-user
  configuration.  This includes user's preferences, such as
  preferred layout and output options.  These properties are
  typically hidden as implementation details, and are often
  changed implicitly as part of other operations.

  authentication properties -- Information used to authenticate
  the user.  This may include such things as passwords, PGP
  keys, and digital certificates.  There are no accessors for
  these properties; they should be used by authenticators only.

Instance Methods [hide private]
 
__init__(self, user_id, role='user', enabled=1, information_properties={}, configuration_properties={}, authentication_properties={})
Create a new user account.
source code
 
GetId(self)
Return the user ID of this user.
source code
 
GetRole(self)
Return the role of this user.
source code
 
IsEnabled(self)
Return true if this account is enabled.
source code
 
GetConfigurationProperty(self, name, default=None)
Return a configuration property.
source code
 
SetConfigurationProperty(self, name, value)
Set the configuration property 'name' to 'value'.
source code
 
GetInfoProperty(self, name, default=None)
Return an informational property.
source code
 
SetInfoProperty(self, name, value)
Set the informational property 'name' to 'value'.
source code
Method Details [hide private]

__init__(self, user_id, role='user', enabled=1, information_properties={}, configuration_properties={}, authentication_properties={})
(Constructor)

source code 

Create a new user account.

'user_id' -- The ID for the user.

'role' -- If "default", this is the default user account (there should be only one). The default account, if provided, is used for otherwise unauthenticated operations. If "admin", this is an administrator account. If "user", this is an ordinary user account.

'enabled' -- If true, this account is enabled; otherwise, disabled.

'information_properties' -- A map contianing information properties.

'configuration_properties' -- A map containing configuration properties.

'authentication_properties' -- A map containing authentication properties.

GetConfigurationProperty(self, name, default=None)

source code 

Return a configuration property.

'name' -- The name of the property.

'default' -- The value to return if this property is not specified for the user account.

GetInfoProperty(self, name, default=None)

source code 

Return an informational property.

'name' -- The name of the property.

'default' -- The value to return if this property is not specified for the user account.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.label-pysrc.html0000664000076400007640000014223211122067152023514 0ustar stefanstefan qm.label
Package qm :: Module label
[hide private]
[frames] | no frames]

Source Code for Module qm.label

  1  ######################################################################## 
  2  # 
  3  # File:   label.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-03-17 
  6  # 
  7  # Contents: 
  8  #   Label 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  from   __future__ import nested_scopes 
 21  import os 
 22  import re 
 23  import string 
 24  import types 
 25   
 26  ######################################################################## 
 27  # Classes 
 28  ######################################################################## 
 29   
30 -class Label:
31 """A 'Label' identifies an entity. 32 33 A 'Label' is a generalization of a filename. Like filenames, labels 34 consist of one or more directories followed by a basename. However, 35 the format used for a label need not be the same as that used by 36 filenames. 37 38 Each label class defines a separator character to take the place of 39 the '/' character used by many file systems. 40 41 All labels are relative labels; no label may begin with a separator 42 character.""" 43
44 - def __init__(self, label):
45 """Construct a new 'Label'. 46 47 'label' -- A string giving the value of the label.""" 48 49 assert type(label) in (types.StringType, types.UnicodeType) 50 self._label = label
51 52
53 - def Join(self, *labels):
54 """Combine this label and the 'labels' into a single label. 55 56 'labels' -- A sequence of strings giving the components of the 57 new label. All but the last are taken as directory names; the 58 last is treated as a basename.""" 59 60 result = self._label 61 for l in labels: 62 if not result: 63 # If the label is empty so far, l is the first component. 64 result = l 65 elif result and result[-1] == self._sep: 66 # If the label thus far ends with a separator, we do not 67 # want to add another one. 68 result += l 69 else: 70 result = result + self._sep + l 71 72 return self.__class__(result)
73 74
75 - def Split(self):
76 """Split the label into a pair '(directory, basename)'. 77 78 returns -- A pair '(directory, basename)', each of which is 79 a label. 80 81 It is always true that 'directory.join(basename)' will return a 82 label equivalent to the original label.""" 83 84 last_sep = self._label.rfind(self._sep) 85 if last_sep != -1: 86 return (self.__class__(self._label[:last_sep]), 87 self.__class__(self._label[last_sep + 1:])) 88 else: 89 return (self.__class__(""), 90 self.__class__(self._label))
91 92
93 - def SplitLeft(self):
94 """Split the label into a pair '(parent, subpath)'. This is 95 the same operation as Split, except the split occurs at the 96 leftmost separator, not the rightmost. 97 98 returns -- A pair '(directory, basename)', each of which is 99 a label. 100 101 It is always true that 'directory.join(basename)' will return a 102 label equivalent to the original label.""" 103 104 first_sep = self._label.find(self._sep) 105 if first_sep != -1: 106 return (self.__class__(self._label[:first_sep]), 107 self.__class__(self._label[first_sep + 1:])) 108 else: 109 return (self.__class__(self._label), 110 self.__class__(""))
111 112
113 - def Basename(self):
114 """Return the basename for the label. 115 116 returns -- A string giving the basename for the label. The 117 value returned for 'l.basename()' is always the same as 118 'l.split()[1]'.""" 119 120 return self.Split()[1]
121 122
123 - def Dirname(self):
124 """Return the directory name for the 'label'. 125 126 returns -- A string giving the directory name for the 'label'. 127 The value returned for 'l.dirname()' is always the same as 128 'l.split()[0]'.""" 129 130 return self.Split()[0]
131 132
133 - def IsValid(self, label, is_component):
134 """Returns true if 'label' is valid. 135 136 'label' -- The string being tested for validity. 137 138 'is_component' -- True if the string being tested is just a 139 single component of a label path. 140 141 returns -- True if 'label' is not valid.""" 142 143 if label and label[0] == self._sep: 144 # All labels are relative; a valid label cannot begin with a 145 # separator. 146 return 0 147 elif is_component and self._sep in label: 148 # A component label cannot contain a separator. 149 return 0 150 elif label.find(self._sep + self._sep) != -1: 151 # It is invalid to have two separators in a row. 152 return 0 153 154 return 1
155 156
157 - def __str__(self):
158 """Return the string form of this label.""" 159 160 return self._label
161 162 ######################################################################## 163 # Functions 164 ######################################################################## 165 166 __thunk_regex = re.compile("[^a-z0-9_]") 167
168 -def thunk(label):
169 """Sanitize and convert 'label' to a valid label. 170 171 Makes a best-effort attempt to keep 'label' recognizable during 172 the conversion. 173 174 returns -- A valid label.""" 175 176 # Strip leading and trailing whitespace. 177 label = string.strip(label) 178 # Lower capital letters. 179 label = string.lower(label) 180 # Replace all invalid characters with underscores. 181 label = string.replace(label, "+", "x") 182 label = __thunk_regex.sub("_", label) 183 # Trim leading underscores. 184 while len(label) > 0 and label[0] == "_": 185 label = label[1:] 186 # Make sure the label isn't empty. 187 if label == "": 188 raise ValueError, "Empty label" 189 return label
190 191 ######################################################################## 192 # Local Variables: 193 # mode: python 194 # indent-tabs-mode: nil 195 # fill-column: 72 196 # End: 197

././@LongLink0000000000000000000000000000016300000000000011565 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.process_target.ProcessTarget.QMTestExecuta0000664000076400007640000001455611122067147033264 0ustar stefanstefan qm.test.classes.process_target.ProcessTarget.QMTestExecutable
Package qm :: Package test :: Package classes :: Module process_target :: Class ProcessTarget :: Class QMTestExecutable
[hide private]
[frames] | no frames]

Class QMTestExecutable

source code

target.qm.executable.Executable --+
                                  |
                                 ProcessTarget.QMTestExecutable

A 'QMTestExecutable' redirects commands to a child process.

Instance Methods [hide private]
 
_InitializeParent(self) source code
 
_InitializeChild(self) source code
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.resource-module.html0000664000076400007640000000210611122067144026146 0ustar stefanstefan resource

Module resource


Classes

Resource

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.report.ReportGenerator-class.html0000664000076400007640000004607411122067150030021 0ustar stefanstefan qm.test.report.ReportGenerator
Package qm :: Package test :: Module report :: Class ReportGenerator
[hide private]
[frames] | no frames]

Class ReportGenerator

source code

A 'ReportGenerator' generates a test report from one or more result files.

Instance Methods [hide private]
 
__init__(self, output, database=None) source code
 
GenerateReport(self, flat, arguments)
Generates a report file with results collected from a set of result files.
source code
 
_LoadTestRuns(self, input)
Load test runs from the provided input.
source code
 
_GetIds(self, test_runs)
Return a list of ids to report results from.
source code
 
_ReportFlat(self, test_runs)
Generate test report with the given set of test runs.
source code
 
_Report(self, test_runs)
Generate test report with the given set of test runs.
source code
 
_ReportSubdirectory(self, directory, test_runs, element=None)
Generate a DOM node for the given directory containing its results.
source code
 
_ReportItem(self, kind, item_id, name, test_runs, parent)
Report a single item.
source code
Method Details [hide private]

GenerateReport(self, flat, arguments)

source code 

Generates a report file with results collected from a set of result files.

'flat' -- True to indicate a flat result listing, False if tests should be reported according to the database directory structure.

'arguments' -- command arguments of the form [result [-e expectation]]+

returns -- None.

_LoadTestRuns(self, input)

source code 

Load test runs from the provided input.

'input' -- A list of pairs of file names referring to result files / expectation files. The expectation file member may be None.

returns -- A list of pairs of TestRun objects.

_GetIds(self, test_runs)

source code 

Return a list of ids to report results from. This list is obtained from the database if it is present, or else by taking the union of all items reported in the test runs.

'test_runs' -- A list of result / expectation table pairs.

returns -- The tuple of resource-setup-ids, test-ids, and resource-cleanup-ids.

_ReportFlat(self, test_runs)

source code 

Generate test report with the given set of test runs. The report will contain a flat list of item ids.

'test_runs' -- List of pairs of TestRun objects.

_Report(self, test_runs)

source code 

Generate test report with the given set of test runs. The report will contain a tree structure with items appearing in their respective subdirectory.

'test_runs' -- List of pairs of TestRun objects.

_ReportSubdirectory(self, directory, test_runs, element=None)

source code 

Generate a DOM node for the given directory containing its results.

'directory' -- The directory for which to generate the report node.

'test_runs' -- The List of TestRuns.

'element' -- DOM element to store results into. If this is None, an element will be created.

returns -- DOM element node containing the xmlified results.

_ReportItem(self, kind, item_id, name, test_runs, parent)

source code 

Report a single item.

'kind' -- The kind of item to report.

'item_id' -- The item id to report.

'name' -- The item's name (usually either the absolute or relative id).

'test_runs' -- The list of test runs.

'parent' -- An XML element to insert new nodes into.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.xmlutil-pysrc.html0000664000076400007640000016171511122067152024142 0ustar stefanstefan qm.xmlutil
Package qm :: Module xmlutil
[hide private]
[frames] | no frames]

Source Code for Module qm.xmlutil

  1  ######################################################################## 
  2  # 
  3  # File:   xmlutil.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-03-18 
  6  # 
  7  # Contents: 
  8  #   Miscellaneous XML-related functions. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import os 
 21  import qm 
 22  import re 
 23  import xml.dom 
 24  import xml.dom.minidom 
 25   
 26  ######################################################################## 
 27  # functions 
 28  ######################################################################## 
 29   
30 -def make_public_id(name):
31 """Return a public ID for the DTD with the given 'name'. 32 33 'name' -- The name of the DTD. 34 35 returns -- A public ID for the DTD.""" 36 37 return "-//QM/%s/%s//EN" % (qm.version, name)
38 39
40 -def make_system_id(name):
41 """Return a system ID for the DTD with the given 'name'. 42 43 'name' -- The name of the DTD, as a relative UNIX path. 44 45 returns -- A URL for the DTD.""" 46 47 return "http://www.codesourcery.com/qm/dtds/%s/%s" % (qm.version, name)
48 49
50 -def load_xml_file(path):
51 """Return a DOM document loaded from the XML file 'path'.""" 52 53 # Open the file. 54 file = open(path, "r") 55 return load_xml(file)
56 57
58 -def load_xml(file):
59 """Return a DOM document loaded from the XML file object 'file'. 60 61 'file' -- A file object, opened for reading. 62 63 returns -- The DOM document contained in 'file'. 64 65 This function closes 'file', whether or not reading the document was 66 successful.""" 67 68 try: 69 document = xml.dom.minidom.parse(file) 70 finally: 71 file.close() 72 return document
73 74
75 -def get_dom_text(node):
76 """Return the text contained in DOM 'node'. 77 78 'node' -- A DOM element node. 79 80 prerequisites -- 'node' is an element node with exactly one child, 81 which is a text node.""" 82 83 assert node.nodeType == xml.dom.Node.ELEMENT_NODE 84 # Normalize the node so that multiple TEXT_NODEs are collapsed into 85 # a single node. 86 node.normalize() 87 # If there are no children, the string is empty. 88 if len(node.childNodes) == 0: 89 return "" 90 # If there is a child, there should be only one. 91 if len(node.childNodes) != 1: 92 raise QMException, "Invalid XML text node." 93 child = node.childNodes[0] 94 if child.nodeType != xml.dom.Node.TEXT_NODE: 95 raise QMException, "Invalid XML text node." 96 return child.data
97 98
99 -def child_tag_predicate(child_tag):
100 """Return a predicate function for finding element nodes by tag. 101 102 returns -- A predicate function that takes a node as its argument 103 and returns true if the node is an element node whose tag is 104 'child_tag'.""" 105 106 return lambda node, tag=child_tag: \ 107 node.nodeType == xml.dom.Node.ELEMENT_NODE \ 108 and node.tagName == tag
109 110
111 -def get_child(node, child_tag):
112 """Return the child element node of 'node' whose tag is 'child_tag'. 113 114 'node' -- A DOM node. It must have exactly one element child with 115 the tag 'child_tag'. 116 117 'child_tag' -- The desired element tag. 118 119 returns -- A child DOM node of 'node'. 120 121 raises -- 'KeyError' if 'node' has no element child with tag 122 'child_tag', or more than one.. """ 123 124 matching_children = \ 125 filter(child_tag_predicate(child_tag), node.childNodes) 126 if len(matching_children) != 1: 127 raise KeyError, child_tag 128 return matching_children[0]
129 130
131 -def get_child_text(node, child_tag, default=None):
132 """Return the text contained in a child of DOM 'node'. 133 134 'child_tag' -- The tag of the child node whose text is to be 135 retrieved. 136 137 'default' -- If 'node' has no child element with tag 'child_tag', 138 returns 'default', unless 'default' is 'None'. 139 140 raises -- 'KeyError' if 'default' is 'None' and 'node' has no child 141 element with tag 'child_tag'.""" 142 143 try: 144 return get_dom_text(get_child(node, child_tag)) 145 except KeyError: 146 if default is not None: 147 return default 148 else: 149 raise
150 151
152 -def get_child_texts(node, child_tag):
153 """Return a sequence of text contents of children. 154 155 'node' -- A DOM node. 156 157 returns -- The list containing all child nodes of 'node' which have 158 tag 'child_tag'. Each child must have exactly one child of its own, 159 which must be a text node.""" 160 161 return map(get_dom_text, node.getElementsByTagName(child_tag))
162 163
164 -def create_dom_text_element(document, tag, text):
165 """Return a DOM element containing a single text node. 166 167 'document' -- The containing DOM document. 168 169 'tag' -- The element tag. 170 171 'text' -- The text contents of the text node.""" 172 173 element = document.createElement(tag) 174 if text != "": 175 text_node = document.createTextNode(text) 176 element.appendChild(text_node) 177 else: 178 # Don't create a child node in this case. For some reason, it 179 # gets written out with an extraneous newline, and therefore 180 # when the text is read in, its no longer an empty string. 181 pass 182 return element
183 184 185 __dom_implementation = xml.dom.minidom.getDOMImplementation() 186
187 -def create_dom_document(public_id, document_element_tag):
188 """Create a DOM document. 189 190 'public_id' -- The (partial) public ID for the DTD. 191 192 'document_element_tag' -- The tag of the main document element. 193 194 returns -- A DOM document node.""" 195 196 public_id = make_public_id(public_id) 197 system_id = make_system_id(public_id.lower() + ".dtd") 198 # Create the document type for the XML document. 199 document_type = __dom_implementation.createDocumentType( 200 qualifiedName=document_element_tag, 201 publicId=public_id, 202 systemId=system_id 203 ) 204 # Create a new DOM document. 205 document = __dom_implementation.\ 206 createDocument(namespaceURI=None, 207 qualifiedName=document_element_tag, 208 doctype=document_type) 209 return document
210 211 212 __hyphen_regex = re.compile("(--+)") 213
214 -def __hyphen_replacement(match):
215 return "-" + " -" * (len(match.group(0)) - 1)
216 217
219 """Return 'text' modified so that it is valid for an XML comment.""" 220 221 # A comment cannot contain two or more hyphens in a row. 222 text = __hyphen_regex.sub(__hyphen_replacement, text) 223 224 return text
225 226 227 ######################################################################## 228 # Local Variables: 229 # mode: python 230 # indent-tabs-mode: nil 231 # fill-column: 72 232 # End: 233

qmtest-2.4.1/share/doc/qmtest/html/manual/qm-module.html0000664000076400007640000005266511122067145022577 0ustar stefanstefan qm
Package qm
[hide private]
[frames] | no frames]

Package qm

source code

Submodules [hide private]

Variables [hide private]
  prefix = '/home/stefan/work/qmtest/qm/..'
  version_info = ('snapshot')
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.label-module.html0000664000076400007640000000250711122067144024425 0ustar stefanstefan label

Module label


Classes

Label

Functions

thunk

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.resource-pysrc.html0000664000076400007640000005557611122067153025261 0ustar stefanstefan qm.test.resource
Package qm :: Package test :: Module resource
[hide private]
[frames] | no frames]

Source Code for Module qm.test.resource

  1  ######################################################################## 
  2  # 
  3  # File:   resource.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2001-10-10 
  6  # 
  7  # Contents: 
  8  #   QMTest Resource class. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  import qm.test.runnable 
 22   
 23  ######################################################################## 
 24  # Classes 
 25  ######################################################################## 
 26   
27 -class Resource(qm.test.runnable.Runnable):
28 """A 'Resource' sets up before a test and cleans up afterwards. 29 30 Some tests take a lot of work to set up. For example, a database 31 test that checks the result of SQL queries may require that the 32 database first be populated with a substantial number of records. 33 If there are many tests that all use the same set of records, it 34 would be wasteful to set up the database for each test. It would 35 be more efficient to set up the database once, run all of the 36 tests, and then remove the databases upon completion. 37 38 You can use a 'Resource' to gain this efficiency. If a test 39 depends on a resource, QMTest will ensure that the resource is 40 available before the test runs. Once all tests that depend on the 41 resource have been run QMTest will destroy the resource. 42 43 Each resource class (i.e., class derived from 'Resource') 44 describes a set of "arguments". Each argument has a name and a 45 type. The values of these arguments determine the design-time 46 parameters for the resource. See the documentation for the 'Test' 47 class for more complete information. 48 49 Each resource class also defines a 'SetUp' method that indicates how 50 to set up the resource, and a 'CleanUp' method that indicates how 51 to clean up afterwards. 52 53 'Resource' is an abstract class. 54 55 You can extend QMTest by providing your own resource class 56 implementation. If the resource classes that come with QMTest 57 cannot be used conveniently with your application domain, you may 58 wish to create a new resource class. 59 60 To create your own resource class, you must create a Python class 61 derived (directly or indirectly) from 'Resource'. The 62 documentation for each method of 'Resource' indicates whether you 63 must override it in your resource class implementation. Some 64 methods may be overridden, but do not need to be. You might want 65 to override such a method to provide a more efficient 66 implementation, but QMTest will work fine if you just use the 67 default version. 68 69 If QMTest calls a method on a resource and that method raises an 70 exception that is not caught within the method itself, QMTest will 71 catch the exception and continue processing.""" 72 73 kind = "resource" 74
75 - def SetUp(self, context, result):
76 """Set up the resource. 77 78 'context' -- A 'Context' giving run-time parameters to the 79 resource. The resource may place additional variables into 80 the 'context'; these variables will be visible to tests that 81 depend on the resource. 82 83 'result' -- A 'Result' object. The outcome will be 84 'Result.PASS' when this method is called. The 'result' may be 85 modified by this method to indicate outcomes other than 86 'Result.PASS' or to add annotations. 87 88 This method should not return a value. 89 90 Derived classes must override this method.""" 91 92 raise NotImplementedError
93 94
95 - def CleanUp(self, result):
96 """Clean up the resource. 97 98 'result' -- A 'Result' object. The outcome will be 99 'Result.PASS' when this method is called. The 'result' may be 100 modified by this method to indicate outcomes other than 101 'Result.PASS' or to add annotations. 102 103 This method should not return a value. 104 105 Derived classes may override this method.""" 106 107 pass
108

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_base-pysrc.html0000664000076400007640000004620611122067161027462 0ustar stefanstefan qm.test.classes.dejagnu_base
Package qm :: Package test :: Package classes :: Module dejagnu_base
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.dejagnu_base

 1  ######################################################################## 
 2  # 
 3  # File:   dejagnu_base.py 
 4  # Author: Mark Mitchell 
 5  # Date:   05/15/2003 
 6  # 
 7  # Contents: 
 8  #   DejaGNUBase 
 9  # 
10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Classes 
16  ######################################################################## 
17   
18 -class DejaGNUBase:
19 """A 'DejaGNUBase' is a base class for tests and resources.""" 20
21 - def _RecordCommand(self, result, command):
22 """Record the execution of 'command'. 23 24 'result' -- The 'Result' for the test. 25 26 'command' -- A sequence of strings, giving the arguments to a 27 command that is about to be executed. 28 29 returns -- An integer giving the the index for this command. 30 This value should be provided to '_RecordCommandOutput' after 31 the command's output is known.""" 32 33 index = self.__next_command 34 key = "DejaGNUTest.command_%d" % index 35 result[key] = result.Quote(" ".join(command)) 36 self.__next_command += 1 37 38 return index
39 40
41 - def _RecordCommandOutput(self, result, index, status, output):
42 """Record the result of running a command. 43 44 'result' -- The 'Result' for the test. 45 46 'index' -- An integer, return from a previous call to 47 '_RecordCommand'. 48 49 'status' -- The exit status from the command. 50 51 'output' -- A string containing the output, if any, from the 52 command.""" 53 54 # Figure out what index to use for this output. 55 56 if status != 0: 57 result["DejaGNUTest.command_status_%d" % index] = str(status) 58 if output: 59 result["DejaGNUTest.command_output_%d" % index] \ 60 = result.Quote(output)
61 62
63 - def _SetUp(self, context):
64 """Prepare to run a test. 65 66 'context' -- The 'Context' in which this test will run. 67 68 This method may be overridden by derived classes, but they 69 must call this version.""" 70 71 # The next command will be the first. 72 self.__next_command = 1
73

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.ChoiceField-class.html0000664000076400007640000004063711122067146026016 0ustar stefanstefan qm.fields.ChoiceField
qm :: fields :: ChoiceField :: Class ChoiceField
[hide private]
[frames] | no frames]

Class ChoiceField

source code

object --+        
         |        
     Field --+    
             |    
     TextField --+
                 |
                ChoiceField
Known Subclasses:

A 'ChoiceField' allows choosing one of several values.

The set of acceptable values can be determined when the field is created or dynamically. The empty string is used as the "no choice" value, and cannot therefore be one of the permitted values.

Instance Methods [hide private]
 
GetItems(self)
Return the options from which to choose.
source code
 
FormatValueAsHtml(self, server, value, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
Validate(self, value)
Validate a field value.
source code

Inherited from TextField: FormatValueAsText, GetHelp, GetValueFromDomNode, MakeDomNodeForValue, ParseFormValue, ParseTextValue, __init__

Inherited from Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

GetItems(self)

source code 

Return the options from which to choose.

returns -- A sequence of strings, each of which will be presented as a choice for the user.

FormatValueAsHtml(self, server, value, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

Overrides: Field.FormatValueAsHtml
(inherited documentation)

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

Overrides: Field.Validate
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.XmlDatabaseAuthenticator-class.html0000664000076400007640000002631411122067151030300 0ustar stefanstefan qm.user.XmlDatabaseAuthenticator
qm :: user :: XmlDatabaseAuthenticator :: Class XmlDatabaseAuthenticator
[hide private]
[frames] | no frames]

Class XmlDatabaseAuthenticator

source code

Authenticator --+
                |
               XmlDatabaseAuthenticator

An authenticator based on contents of the XML user database.

Instance Methods [hide private]
 
__init__(self, database)
Create a new authenticator.
source code
 
AuthenticateDefaultUser(self)
Authenticate for the default user, if one is provided.
source code
 
AuthenticateWebRequest(self, request)
Authenticate a login web request.
source code
 
AuthenticatePassword(self, user_name, password) source code
Method Details [hide private]

__init__(self, database)
(Constructor)

source code 

Create a new authenticator.

Authentication is performed based on information stored in 'XmlDatabase' instance 'database'.

AuthenticateDefaultUser(self)

source code 

Authenticate for the default user, if one is provided.

returns -- The user ID of the default user.

Overrides: Authenticator.AuthenticateDefaultUser
(inherited documentation)

AuthenticateWebRequest(self, request)

source code 

Authenticate a login web request.

'request' -- A web request containing the user's login information.

returns -- The user ID of the authenticated user.

Overrides: Authenticator.AuthenticateWebRequest
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.dg_test-module.html0000664000076400007640000000210711122067144027405 0ustar stefanstefan dg_test

Module dg_test


Classes

DGTest

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.target.Target-class.html0000664000076400007640000012427411122067150026077 0ustar stefanstefan qm.test.target.Target
Package qm :: Package test :: Module target :: Class Target
[hide private]
[frames] | no frames]

Class Target

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     Target

Base class for target implementations.

A 'Target' is an entity that can run tests. QMTest can spread the workload from multiple tests across multiple targets. In addition, a single target can run more than one test at once.

'Target' is an abstract class.

You can extend QMTest by providing your own target class implementation.

To create your own target class, you must create a Python class derived (directly or indirectly) from 'Target'. The documentation for each method of 'Target' indicates whether you must override it in your target class implementation. Some methods may be overridden, but do not need to be. You might want to override such a method to provide a more efficient implementation, but QMTest will work fine if you just use the default version.

Nested Classes [hide private]
  __ResourceSetUpException
An exception indicating that a resource could not be set up.

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, arguments=None, **args)
Construct a 'Target'.
source code
 
GetName(self)
Return the name of the target.
source code
 
GetGroup(self)
Return the group of which the target is a member.
source code
 
GetDatabase(self)
Return the 'Database' containing the tests this target will run.
source code
 
IsIdle(self)
Return true if the target is idle.
source code
 
IsInGroup(self, group_pattern)
Returns true if this 'Target' is in a particular group.
source code
 
Start(self, response_queue, engine=None)
Start the target.
source code
 
Stop(self)
Stop the target.
source code
 
RunTest(self, descriptor, context)
Run the test given by 'test_id'.
source code
 
_RecordResult(self, result)
Record the 'result'.
source code
 
_BeginResourceSetUp(self, resource_name)
Begin setting up the indicated resource.
source code
 
_FinishResourceSetUp(self, resource, result, properties)
Finish setting up a resource.
source code
 
__SetUpResources(self, descriptor, context)
Set up all the resources associated with 'descriptor'.
source code
 
_SetUpResource(self, resource_name, context)
Set up the resource given by 'resource_id'.
source code
 
_CleanUpResource(self, name, resource)
Clean up the 'resource'.
source code
 
_GetTemporaryDirectory(self)
Return the path to a temporary directory.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "name", title= "Name", ...
A list of the arguments to the extension class.
  kind = "target"
A string giving kind of extension is implemented by the class.
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, arguments=None, **args)
(Constructor)

source code 

Construct a 'Target'.

'database' -- The 'Database' containing the tests that will be run.

'arguments' -- As for 'Extension.__init__'.

'args' -- As for 'Extension.__init__'.

Overrides: object.__init__

GetName(self)

source code 

Return the name of the target.

Derived classes must not override this method.

GetGroup(self)

source code 

Return the group of which the target is a member.

Derived classes must not override this method.

GetDatabase(self)

source code 

Return the 'Database' containing the tests this target will run.

returns -- The 'Database' containing the tests this target will run.

Derived classes must not override this method.

IsIdle(self)

source code 

Return true if the target is idle.

returns -- True if the target is idle. If the target is idle, additional tasks may be assigned to it.

Derived classes must override this method.

IsInGroup(self, group_pattern)

source code 

Returns true if this 'Target' is in a particular group.

'group_pattern' -- A string giving a regular expression.

returns -- Returns true if the 'group_pattern' denotes a regular expression that matches the group for this 'Target', false otherwise.

Start(self, response_queue, engine=None)

source code 

Start the target.

'response_queue' -- The 'Queue' in which the results of test executions are placed.

'engine' -- The 'ExecutionEngine' that is starting the target, or 'None' if this target is being started without an 'ExecutionEngine'.

Derived classes may override this method, but the overriding method must call this method at some point during its execution.

Stop(self)

source code 

Stop the target.

Clean up all resources that have been set up on this target and take whatever other actions are required to stop the target.

Derived classes may override this method.

RunTest(self, descriptor, context)

source code 

Run the test given by 'test_id'.

'descriptor' -- The 'TestDescriptor' for the test.

'context' -- The 'Context' in which to run the test.

Derived classes may override this method.

_RecordResult(self, result)

source code 

Record the 'result'.

'result' -- A 'Result' of a test or resource execution.

Derived classes may override this method, but the overriding method must call this method at some point during its execution.

_BeginResourceSetUp(self, resource_name)

source code 

Begin setting up the indicated resource.

'resource_name' -- A string naming a resource.

returns -- If at attempt to set up the resource has already been made, returns a tuple '(resource, outcome, properties)'. The 'resource' is the 'Resource' object itself, but may be 'None' if the resource could not be set up. The 'outcome' indicates the outcome that resulted when the resource was set up. The 'properties' are a map from strings to strings indicating properties added by this resource.

If the resource has not been set up, but _BeginResourceSetUp has already been called for the resource, then the contents of the tuple will all be 'None'.

If this is the first time _BeginResourceSetUp has been called for this resource, then 'None' is returned, but the resource is marked as in the process of being set up. It is the caller's responsibility to finish setting it up by calling '_FinishResourceSetUp'.

_FinishResourceSetUp(self, resource, result, properties)

source code 

Finish setting up a resource.

'resource' -- The 'Resource' itself.

'result' -- The 'Result' associated with setting up the resource.

'properties' -- A dictionary of additional context properties that should be provided to tests that depend on this resource.

returns -- A tuple of the same form as is returned by '_BeginResourceSetUp' when the resource has already been set up.

__SetUpResources(self, descriptor, context)

source code 

Set up all the resources associated with 'descriptor'.

'descriptor' -- The 'TestDescriptor' or 'ResourceDescriptor' indicating the test or resource that is about to be run.

'context' -- The 'Context' in which the resources will be executed.

returns -- A tuple of the same form as is returned by '_BeginResourceSetUp' when the resource has already been set up.

_SetUpResource(self, resource_name, context)

source code 

Set up the resource given by 'resource_id'.

'resource_name' -- The name of the resource to be set up.

'context' -- The 'Context' in which to run the resource.

returns -- A map from strings to strings indicating additional properties added by this resource.

_CleanUpResource(self, name, resource)

source code 

Clean up the 'resource'.

'resource' -- The 'Resource' that should be cleaned up.

'name' -- The name of the resource itself.

_GetTemporaryDirectory(self)

source code 

Return the path to a temporary directory.

returns -- The path to a temporary directory to pass along to tests and resources via the 'TMPDIR_CONTEXT_PROPERTY'.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "name", title= "Name", description= """The \
name of this target.

            The name of the target.  The target name will be recorded
            in any tests executed on that target so that you can see
            where the test was run.""", default_value= ""), qm.fields.\
TextField(name= "group", title= "Group", description= """The group ass\
ociated with this target.
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.cmdline.QMTest-class.html0000664000076400007640000026661611122067150026162 0ustar stefanstefan qm.test.cmdline.QMTest
Package qm :: Package test :: Module cmdline :: Class QMTest
[hide private]
[frames] | no frames]

Class QMTest

source code

An instance of QMTest.

Instance Methods [hide private]
 
__init__(self, argument_list, path)
Construct a new QMTest.
source code
 
__del__(self)
Clean up global variables.
source code
 
HasGlobalOption(self, option)
Return true if 'option' was specified as a global command.
source code
 
GetGlobalOption(self, option, default=None)
Return the value of global 'option', or 'default' if omitted.
source code
 
HasCommandOption(self, option)
Return true if command 'option' was specified.
source code
 
GetCommandOption(self, option, default=None)
Return the value of command 'option'.
source code
 
Execute(self)
Execute the command.
source code
 
GetDatabase(self)
Return the test database to use.
source code
 
GetDatabaseIfAvailable(self)
Return the test database to use.
source code
 
GetTargetFileName(self)
Return the path to the file containing target specifications.
source code
 
GetTargetsFromFile(self, file_name)
Return the 'Target's specified in 'file_name'.
source code
 
GetTargets(self)
Return the 'Target' objects specified by the user.
source code
 
GetTracer(self)
Return the 'Tracer' associated with this instance of QMTest.
source code
 
MakeContext(self)
Construct a 'Context' object for running tests.
source code
 
GetExecutablePath(self)
Return the path to the QMTest executable.
source code
 
GetFileResultStreamClass(self)
Return the 'ResultStream' class used for results files.
source code
 
GetTextResultStreamClass(self)
Return the 'ResultStream' class used for textual feedback.
source code
 
__GetAttributeOptions(self, expect_value=True)
Return the attributes specified on the command line.
source code
 
__GetAnnotateOptions(self)
Return all annotate options.
source code
 
__ExecuteCreate(self)
Create a new extension file.
source code
 
__ExecuteCreateTdb(self, db_path)
Handle the command for creating a new test database.
source code
 
__ExecuteCreateTarget(self)
Create a new target file.
source code
 
__ExecuteExtensions(self)
List the available extension classes.
source code
 
__ExecuteDescribe(self)
Describe an extension.
source code
 
__ExecuteList(self)
List the contents of the database.
source code
 
__ExecuteRegister(self)
Register a new extension class.
source code
 
__ExecuteSummarize(self)
Read in test run results and summarize.
source code
 
__ExecuteRemote(self)
Execute the 'remote' command.
source code
 
__ExecuteReport(self)
Execute a 'report' command.
source code
 
__ExecuteRun(self)
Execute a 'run' command.
source code
 
__ExecuteServer(self)
Process the server command.
source code
 
__WriteCommandHelp(self, command)
Write out help information about 'command'.
source code
 
__FilterTestsToRun(self, test_ids, expectations)
Return those tests from 'test_ids' that should be run.
source code
 
__CheckExtensionKind(self, kind)
Check that 'kind' is a valid extension kind.
source code
 
__CreateResultStreams(self, output_file, annotations, expectations)
Return the result streams to use.
source code
Class Variables [hide private]
  __extension_kinds_string = _make_comma_separated_string(base.e...
A string listing the available extension kinds.
  db_path_environment_variable = "QMTEST_DB_PATH"
The environment variable specifying the test database path.
  summary_formats = "brief", "full", "stats", "batch", "none"
Valid formats for result summaries.
  context_file_name = "context"
The default name of a context file.
  expectations_file_name = "expectations.qmr"
The default name of a file containing expectations.
  results_file_name = "results.qmr"
The default name of a file containing results.
  target_file_name = "targets"
The default name of a file containing targets.
  help_option_spec = "h", "help", None, "Display usage summary."
  version_option_spec = None, "version", None, "Display version ...
  db_path_option_spec = "D", "tdb", "PATH", "Path to the test da...
  extension_output_option_spec = "o", "output", "FILE", "Write t...
  extension_id_option_spec = "i", "id", "NAME", "Write the exten...
  output_option_spec = "o", "output", "FILE", "Write test result...
  no_output_option_spec = None, "no-output", None, "Don't genera...
  outcomes_option_spec = "O", "outcomes", "FILE", "Use expected ...
  expectations_option_spec = "e", "expectations", "FILE", "Use e...
  context_option_spec = "c", "context", "KEY=VALUE", "Add or ove...
  context_file_spec = "C", "load-context", "FILE", "Read context...
  daemon_option_spec = None, "daemon", None, "Run as a daemon."
  port_option_spec = "P", "port", "PORT", "Server port number."
  address_option_spec = "A", "address", "ADDRESS", "Local address."
  log_file_option_spec = None, "log-file", "PATH", "Log file name."
  no_browser_option_spec = None, "no-browser", None, "Do not ope...
  pid_file_option_spec = None, "pid-file", "PATH", "Process ID f...
  concurrent_option_spec = "j", "concurrency", "COUNT", "Execute...
  targets_option_spec = "T", "targets", "FILE", "Use FILE as the...
  random_option_spec = None, "random", None, "Run the tests in a...
  rerun_option_spec = None, "rerun", "FILE", "Rerun the tests th...
  seed_option_spec = None, "seed", "INTEGER", "Seed the random n...
  format_option_spec = "f", "format", "FORMAT", "Specify the sum...
  result_stream_spec = None, "result-stream", "CLASS-NAME", "Spe...
  annotation_option_spec = "a", "annotate", "NAME=VALUE", "Set a...
  tdb_class_option_spec = "c", "class", "CLASS-NAME", "Specify t...
  attribute_option_spec = "a", "attribute", "NAME", "Get an attr...
  set_attribute_option_spec = "a", "attribute", "KEY=VALUE", "Se...
  extension_kind_option_spec = "k", "kind", "EXTENSION-KIND", "S...
  report_output_option_spec = "o", "output", "FILE", "Write test...
  report_flat_option_spec = "f", "flat", None, """Generate a fla...
  results_option_spec = "R", "results", "DIRECTORY", "Read in al...
  list_long_option_spec = "l", "long", None, "Use a detailed out...
  list_details_option_spec = "d", "details", None, "Display deta...
  list_recursive_option_spec = "R", "recursive", None, "Recursiv...
  conflicting_option_specs = output_option_spec, no_output_optio...
  global_options_spec = [help_option_spec, version_option_spec, ...
  commands_spec = [("create", "Create (or update) an extension."...
  __version_output = "QMTest %s\n" "Copyright (C) 2002 - 2007 Co...
The string printed when the --version option is used.
Method Details [hide private]

__init__(self, argument_list, path)
(Constructor)

source code 

Construct a new QMTest.

Parses the argument list but does not execute the command.

'argument_list' -- The arguments to QMTest, not including the initial argv[0].

'path' -- The path to the QMTest executable.

HasGlobalOption(self, option)

source code 

Return true if 'option' was specified as a global command.

'command' -- The long name of the option, but without the preceding "--".

returns -- True if the option is present.

GetCommandOption(self, option, default=None)

source code 

Return the value of command 'option'.

'option' -- The long form of an command-specific option.

'default' -- The default value to be returned if the 'option' was not specified. This option should be the kind of an option that takes an argument.

returns -- The value specified by the option, or 'default' if the option was not specified.

Execute(self)

source code 

Execute the command.

returns -- 0 if the command was executed successfully. 1 if there was a problem or if any tests run had unexpected outcomes.

GetDatabase(self)

source code 

Return the test database to use.

returns -- The 'Database' to use for this execution. Raises an exception if no 'Database' is available.

GetDatabaseIfAvailable(self)

source code 

Return the test database to use.

returns -- The 'Database' to use for this execution, or 'None' if no 'Database' is available.

GetTargetFileName(self)

source code 

Return the path to the file containing target specifications.

returns -- The path to the file containing target specifications.

GetTargetsFromFile(self, file_name)

source code 

Return the 'Target's specified in 'file_name'.

returns -- A list of the 'Target' objects specified in the target specification file 'file_name'.

GetTargets(self)

source code 

Return the 'Target' objects specified by the user.

returns -- A sequence of 'Target' objects.

GetTracer(self)

source code 

Return the 'Tracer' associated with this instance of QMTest.

returns -- The 'Tracer' associated with this instance of QMTest.

GetExecutablePath(self)

source code 

Return the path to the QMTest executable.

returns -- A string giving the path to the QMTest executable. This is the path that should be used to invoke QMTest recursively. Returns 'None' if the path to the QMTest executable is uknown.

GetFileResultStreamClass(self)

source code 

Return the 'ResultStream' class used for results files.

returns -- The 'ResultStream' class used for results files.

GetTextResultStreamClass(self)

source code 

Return the 'ResultStream' class used for textual feedback.

returns -- the 'ResultStream' class used for textual feedback.

__GetAttributeOptions(self, expect_value=True)

source code 

Return the attributes specified on the command line.

'expect_value' -- True if the attribute is to be parsed as an assignment.

returns -- A dictionary. If expect_value is True, it maps attribute names (strings) to values (strings). Else it contains the raw attribute strings, mapping to None. There is an entry for each attribute specified with '--attribute' on the command line.

__GetAnnotateOptions(self)

source code 

Return all annotate options.

returns -- A dictionary containing the annotation name / value pairs.

__ExecuteCreateTdb(self, db_path)

source code 

Handle the command for creating a new test database.

'db_path' -- The path at which to create the new test database.

__WriteCommandHelp(self, command)

source code 

Write out help information about 'command'.

'command' -- The name of the command for which help information is required.

__FilterTestsToRun(self, test_ids, expectations)

source code 

Return those tests from 'test_ids' that should be run.

'test_ids' -- A sequence of test ids.

'expectations' -- An ExpectationDatabase.

returns -- Those elements of 'test_names' that are not to be skipped. If 'a' precedes 'b' in 'test_ids', and both 'a' and 'b' are present in the result, 'a' will precede 'b' in the result.

__CheckExtensionKind(self, kind)

source code 

Check that 'kind' is a valid extension kind.

'kind' -- A string giving the name of an extension kind. If the 'kind' does not name a valid extension kind, an appropriate exception is raised.

__CreateResultStreams(self, output_file, annotations, expectations)

source code 

Return the result streams to use.

'output_file' -- If not 'None', the name of a file to which the standard results file format should be written.

'annotations' -- A dictionary with annotations for this test run.

'expectations' -- An ExpectationDatabase.

returns -- A list of 'ResultStream' objects, as indicated by the user.


Class Variable Details [hide private]

__extension_kinds_string

A string listing the available extension kinds.

Value:
_make_comma_separated_string(base.extension_kinds, "or")

version_option_spec

Value:
None, "version", None, "Display version information."

db_path_option_spec

Value:
"D", "tdb", "PATH", "Path to the test database."

extension_output_option_spec

Value:
"o", "output", "FILE", "Write the extension to FILE.",

extension_id_option_spec

Value:
"i", "id", "NAME", "Write the extension to the database as NAME.",

output_option_spec

Value:
"o", "output", "FILE", "Write test results to FILE (- for stdout)."

no_output_option_spec

Value:
None, "no-output", None, "Don't generate test results."

outcomes_option_spec

Value:
"O", "outcomes", "FILE", "Use expected outcomes in FILE."

expectations_option_spec

Value:
"e", "expectations", "FILE", "Use expectations in FILE."

context_option_spec

Value:
"c", "context", "KEY=VALUE", "Add or override a context property."

context_file_spec

Value:
"C", "load-context", "FILE", "Read context from a file (- for stdin)."

no_browser_option_spec

Value:
None, "no-browser", None, "Do not open a new browser window."

pid_file_option_spec

Value:
None, "pid-file", "PATH", "Process ID file name."

concurrent_option_spec

Value:
"j", "concurrency", "COUNT", "Execute tests in COUNT concurrent thread\
s."

targets_option_spec

Value:
"T", "targets", "FILE", "Use FILE as the target specification file."

random_option_spec

Value:
None, "random", None, "Run the tests in a random order."

rerun_option_spec

Value:
None, "rerun", "FILE", "Rerun the tests that failed."

seed_option_spec

Value:
None, "seed", "INTEGER", "Seed the random number generator."

format_option_spec

Value:
"f", "format", "FORMAT", "Specify the summary format."

result_stream_spec

Value:
None, "result-stream", "CLASS-NAME", "Specify the results file format.\
"

annotation_option_spec

Value:
"a", "annotate", "NAME=VALUE", "Set an additional annotation to be wri\
tten to the result stream(s)."

tdb_class_option_spec

Value:
"c", "class", "CLASS-NAME", "Specify the test database class.",

attribute_option_spec

Value:
"a", "attribute", "NAME", "Get an attribute of the extension class."

set_attribute_option_spec

Value:
"a", "attribute", "KEY=VALUE", "Set an attribute of the extension clas\
s."

extension_kind_option_spec

Value:
"k", "kind", "EXTENSION-KIND", "Specify the kind of extension class."

report_output_option_spec

Value:
"o", "output", "FILE", "Write test report to FILE (- for stdout)."

report_flat_option_spec

Value:
"f", "flat", None, """Generate a flat listing of test results, instead\
 of reproducing the
        database directory tree in the report."""

results_option_spec

Value:
"R", "results", "DIRECTORY", "Read in all results (*.qmr) files from D\
IRECTORY."

list_long_option_spec

Value:
"l", "long", None, "Use a detailed output format."

list_details_option_spec

Value:
"d", "details", None, "Display details for individual items."

list_recursive_option_spec

Value:
"R", "recursive", None, "Recursively list the contents of directories.\
"

conflicting_option_specs

Value:
output_option_spec, no_output_option_spec, (concurrent_option_spec, ta\
rgets_option_spec), (extension_output_option_spec, extension_id_option\
_spec), (expectations_option_spec, outcomes_option_spec),

global_options_spec

Value:
[help_option_spec, version_option_spec, db_path_option_spec,]

commands_spec

Value:
[("create", "Create (or update) an extension.", "EXTENSION-KIND CLASS-\
NAME(ATTR1 = 'VAL1', ATTR2 = 'VAL2', ...)", """Create (or update) an e\
xtension.

         The EXTENSION-KIND indicates what kind of extension to
         create; it must be one of """+ __extension_kinds_string+ """.

         The CLASS-NAME indicates the name of the extension class, or
...

__version_output

The string printed when the --version option is used.

There is one fill-in, for a string, which should contain the version number.

Value:
"QMTest %s\n" "Copyright (C) 2002 - 2007 CodeSourcery, Inc.\n" "QMTest\
 comes with ABSOLUTELY NO WARRANTY\n" "For more information about QMTe\
st visit http://www.qmtest.com\n"

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index.html0000664000076400007640000004466311122067144024124 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

A



qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.xml_database-module.html0000664000076400007640000000232411122067144030401 0ustar stefanstefan xml_database

Module xml_database


Classes

TestFileError
XMLDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Raise-module.html0000664000076400007640000001701411122067145031307 0ustar stefanstefan qm.external.DocumentTemplate.DT_Raise
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Raise
[hide private]
[frames] | no frames]

Module DT_Raise

source code

Raising exceptions

Errors can be raised from DTML using the 'raise' tag.

For example:

<!--#if expr="condition_that_tests_input"-->
   <!--#raise type="Input Error"-->
       The value you entered is not valid
   <!--#/raise-->
<!--#/if-->

Version: 1069

Classes [hide private]
  Raise
Variables [hide private]
  __rcs_id__ = '$Id: DT_Raise.py 1069 2008-11-13 21:55:43Z stefa...
Variables Details [hide private]

__rcs_id__

Value:
'$Id: DT_Raise.py 1069 2008-11-13 21:55:43Z stefan $'

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DocumentTemplate-module.html0000664000076400007640000002121311122067145033123 0ustar stefanstefan qm.external.DocumentTemplate.DocumentTemplate
Package qm :: Package external :: Package DocumentTemplate :: Module DocumentTemplate
[hide private]
[frames] | no frames]

Module DocumentTemplate

source code

Document templates with fill-in fields

Document templates provide for creation of textual documents, such as
HTML pages, from template source by inserting data from python objects
and name-spaces.

When a document template is created, a collection of default values to
be inserted may be specified with a mapping object and with keyword
arguments.

A document templated may be called to create a document with values
inserted.  When called, an instance, a mapping object, and keyword
arguments may be specified to provide values to be inserted.  If an
instance is provided, the document template will try to look up values
in the instance using getattr, so inheritence of values is supported.
If an inserted value is a function, method, or class, then an attempt
will be made to call the object to obtain values.  This allows
instance methods to be included in documents.

Document templates masquerade as functions, so the python object
publisher (Bobo) will call templates that are stored as instances of
published objects. Bobo will pass the object the template was found in
and the HTTP request object.

Two source formats are supported:

   Extended Python format strings (EPFS) --
      This format is based on the insertion by name format strings
      of python with additional format characters, '[' and ']' to
      indicate block boundaries.  In addition, parameters may be
      used within formats to control how insertion is done.

      For example:

         %%(date fmt=DayOfWeek upper)s

      causes the contents of variable 'date' to be inserted using
      custom format 'DayOfWeek' and with all lower case letters
      converted to upper case.

   HTML --
      This format uses HTML server-side-include syntax with
      commands for inserting text. Parameters may be included to
      customize the operation of a command.

      For example:

         <!--#var total fmt=12.2f-->

      is used to insert the variable 'total' with the C format
      '12.2f'.

Document templates support conditional and sequence insertion

    Document templates extend python string substitition rules with a
    mechanism that allows conditional insertion of template text and that
    allows sequences to be inserted with element-wise insertion of
    template text.

Access Control

    Document templates provide a basic level of access control by
    preventing access to names beginning with an underscore.
    Additional control may be provided by providing document templates
    with a 'guarded_getattr' and 'guarded_getitem' method.  This would
    typically be done by subclassing one or more of the DocumentTemplate
    classes.

    If provided, the the 'guarded_getattr' method will be called when
    objects are accessed as instance attributes or when they are
    accessed through keyed access in an expression.

Document Templates may be created 4 ways:

    DocumentTemplate.String -- Creates a document templated from a
        string using an extended form of python string formatting.

    DocumentTemplate.File -- Creates a document templated bound to a
        named file using an extended form of python string formatting.
        If the object is pickled, the file name, rather than the file
        contents is pickled.  When the object is unpickled, then the
        file will be re-read to obtain the string.  Note that the file
        will not be read until the document template is used the first
        time.

    DocumentTemplate.HTML -- Creates a document templated from a
        string using HTML server-side-include rather than
        python-format-string syntax.

    DocumentTemplate.HTMLFile -- Creates an HTML document template
        from a named file.


Version: 1069

Variables [hide private]
  ParseError = 'Document Template Parse Error'
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.expectation_database-module.html0000664000076400007640000000220011122067144030461 0ustar stefanstefan expectation_database

Module expectation_database


Classes

ExpectationDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_test-pysrc.html0000664000076400007640000050135211122067157027532 0ustar stefanstefan qm.test.classes.dejagnu_test
Package qm :: Package test :: Package classes :: Module dejagnu_test
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.dejagnu_test

  1  ######################################################################## 
  2  # 
  3  # File:   dejagnu_test.py 
  4  # Author: Mark Mitchell 
  5  # Date:   04/16/2003 
  6  # 
  7  # Contents: 
  8  #   DejaGNUTest 
  9  # 
 10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  from   dejagnu_base import DejaGNUBase 
 21  import os 
 22  import qm 
 23  from   qm.common import QMException 
 24  from   qm.executable import RedirectedExecutable 
 25  from   qm.test.test import Test 
 26  from   qm.test.result import Result 
 27   
 28  ######################################################################## 
 29  # Classes 
 30  ######################################################################## 
 31   
32 -class DejaGNUTest(Test, DejaGNUBase):
33 """A 'DejaGNUTest' emulates a DejaGNU test. 34 35 See 'framework.exp' in the DejaGNU distribution for more 36 information.""" 37 38 arguments = [ 39 qm.fields.AttachmentField( 40 name="source_file", 41 title="Source File", 42 description="""The source file."""), 43 ] 44 45 PASS = "PASS" 46 FAIL = "FAIL" 47 KFAIL = "KFAIL" 48 KPASS = "KPASS" 49 XPASS = "XPASS" 50 XFAIL = "XFAIL" 51 WARNING = "WARNING" 52 ERROR = "ERROR" 53 UNTESTED = "UNTESTED" 54 UNRESOLVED = "UNRESOLVED" 55 UNSUPPORTED = "UNSUPPORTED" 56 57 dejagnu_outcomes = ( 58 PASS, FAIL, XPASS, XFAIL, WARNING, ERROR, UNTESTED, 59 UNRESOLVED, UNSUPPORTED 60 ) 61 """The DejaGNU test outcomes.""" 62 63 outcome_map = { 64 PASS : Result.PASS, 65 FAIL : Result.FAIL, 66 KFAIL : Result.FAIL, 67 KPASS : Result.PASS, 68 XPASS : Result.PASS, 69 XFAIL : Result.FAIL, 70 WARNING : Result.PASS, 71 ERROR : Result.ERROR, 72 UNTESTED : Result.UNTESTED, 73 UNRESOLVED : Result.UNTESTED, 74 UNSUPPORTED : Result.UNTESTED 75 } 76 """A map from DejaGNU outcomes to QMTest outcomes.""" 77 78 executable_timeout = 300 79 """The number of seconds a program is permitted to run on the target.""" 80 81 RESULT_PREFIX = "DejaGNUTest.result_" 82 """The prefix for DejaGNU result annotations. 83 84 All results that would be generated by DejaGNU are inserted into 85 the QMTest result as annotations beginning with this prefix. The 86 prefix is followed by an 1-indexed integer; earlier results are 87 inserted with lower numbers.""" 88
89 - class BuildExecutable(RedirectedExecutable):
90 """A 'BuildExecutable' runs on the build machine. 91 92 Classes derived from 'DejaGNUTest' may provide derived 93 versions of this class.""" 94
95 - def _StderrPipe(self):
96 97 # Combine stdout/stderr into a single stream. 98 return None
99 100
101 - def _GetTargetEnvironment(self, context):
102 """Return additional environment variables to set on the target. 103 104 'context' -- The 'Context' in which this test is running. 105 106 returns -- A map from strings (environment variable names) to 107 strings (values for those variables). These new variables are 108 added to the environment when a program executes on the 109 target.""" 110 111 return {}
112 113
114 - def _RunBuildExecutable(self, context, result, file, args = [], 115 dir = None):
116 """Run 'file' on the target. 117 118 'context' -- The 'Context' in which this test is running. 119 120 'result' -- The 'Result' of this test. 121 122 'file' -- The path to the executable file. 123 124 'args' -- The arguments to the 'file'. 125 126 'dir' -- The directory in which the program should execute. 127 128 returns -- A pair '(status, output)'. The 'status' is the 129 exit status from the command; the 'output' is the combined 130 results of the standard output and standard error streams.""" 131 132 executable = self.BuildExecutable(self.executable_timeout) 133 command = [file] + args 134 index = self._RecordCommand(result, command) 135 status = executable.Run(command, None, dir) 136 output = executable.stdout 137 self._RecordCommandOutput(result, index, status, output) 138 139 return status, output
140 141
142 - def _RunTargetExecutable(self, context, result, file):
143 """Run 'file' on the target. 144 145 'context' -- The 'Context' in which this test is running. 146 147 'result' -- The 'Result' of this test. 148 149 'file' -- The path to the executable file. 150 151 returns -- One of the 'dejagnu_outcomes'.""" 152 153 host = context['CompilerTable.target'] 154 index = self._RecordCommand(result, [file]) 155 environment = self._GetTargetEnvironment(context) 156 status, output = host.Run(file, [], environment) 157 self._RecordCommandOutput(result, index, status, output) 158 # Figure out whether the execution was successful. 159 if os.WIFEXITED(status) and os.WEXITSTATUS(status) == 0: 160 outcome = self.PASS 161 else: 162 outcome = self.FAIL 163 164 return outcome
165 166
167 - def _RecordDejaGNUOutcome(self, result, outcome, message, 168 expectation = None):
169 """Record a DejaGNU outcome. 170 171 'result' -- A 'Result' object. 172 173 'outcome' -- One of the 'dejagnu_outcomes'. 174 175 'message' -- A string, explaining the outcome. 176 177 'expectation' -- If not 'None, the DejaGNU outcome that was 178 expected.""" 179 180 # If the test was expected to fail, transform PASS or FAIL 181 # into XPASS or XFAIL, respectively. 182 if expectation == self.FAIL: 183 if outcome == self.PASS: 184 outcome = self.XPASS 185 elif outcome == self.FAIL: 186 outcome = self.XFAIL 187 188 # Create an annotation corresponding to the DejaGNU outcome. 189 key = "%s%d" % (self.RESULT_PREFIX, self.__next_result) 190 self.__next_result += 1 191 result[key] = outcome + ": " + message 192 # If the test was passing until now, give it a new outcome. 193 new_outcome = self.outcome_map[outcome] 194 if (new_outcome 195 and new_outcome != Result.PASS 196 and result.GetOutcome() == Result.PASS): 197 result.SetOutcome(new_outcome) 198 result[Result.CAUSE] = message
199 200
201 - def _Unresolved(self, result, message):
202 """Record an 'unresolved' DejaGNU outcome. 203 204 This function is identical to 'RecordDejaGNUOutcome', except 205 that the 'outcome' is always 'UNRESOLVED'.""" 206 207 self._RecordDejaGNUOutcome(result, self.UNRESOLVED, message)
208 209 210
211 - def _Error(self, message):
212 """Raise an exception indicating an error in the test. 213 214 'message' -- A description of the problem. 215 216 This function is used when the original Tcl code in DejaGNU 217 would have used the Tcl 'error' primitive. These situations 218 indicate problems with the test itself, such as incorrect 219 usage of special test commands.""" 220 221 raise DejaGNUError, message
222 223
224 - def _GetSourcePath(self):
225 """Return the path to the primary source file. 226 227 returns -- A string giving the path to the primary source 228 file.""" 229 230 return self.source_file.GetDataFile()
231 232
233 - def _GetBuild(self, context):
234 """Return the GNU triplet corresponding to the build machine. 235 236 'context' -- The 'Context' in which the test is running. 237 238 returns -- The GNU triplet corresponding to the target 239 machine, i.e,. the machine on which the compiler will run.""" 240 241 return context.get("DejaGNUTest.build") or self._GetTarget(context)
242 243
244 - def _GetTarget(self, context):
245 """Return the GNU triplet corresponding to the target machine. 246 247 'context' -- The 'Context' in which the test is running. 248 249 returns -- The GNU triplet corresponding to the target 250 machine, i.e,. the machine on which the programs generated by 251 the compiler will run.""" 252 253 return context["DejaGNUTest.target"]
254 255
256 - def _IsNative(self, context):
257 """Returns true if the build and target machines are the same. 258 259 'context' -- The 'Context' in which this test is running. 260 261 returns -- True if this test is runing "natively", i.e., if 262 the build and target machines are the same.""" 263 264 return self._GetTarget(context) == self._GetBuild(context)
265 266
267 - def _SetUp(self, context):
268 """Prepare to run a test. 269 270 'context' -- The 'Context' in which this test will run. 271 272 This method may be overridden by derived classes, but they 273 must call this version.""" 274 275 super(DejaGNUTest, self)._SetUp(context) 276 # The next DejaGNU result will be the first. 277 self.__next_result = 1
278 279
280 - def _ParseTclWords(self, s, variables = {}):
281 """Separate 's' into words, in the same way that Tcl would. 282 283 's' -- A string. 284 285 'variables' -- A map from variable names to values. If Tcl 286 variable substitutions are encountered in 's', the 287 corresponding value from 'variables' will be used. 288 289 returns -- A sequence of strings, each of which is a Tcl 290 word. 291 292 Command substitution is not supported and results in an 293 exceptions. Invalid inputs (like the string consisting of a 294 single quote) also result in exceptions. 295 296 See 'Tcl and the Tk Toolkit', by John K. Ousterhout, copyright 297 1994 by Addison-Wesley Publishing Company, Inc. for details 298 about the syntax of Tcl.""" 299 300 # There are no words yet. 301 words = [] 302 # There is no current word. 303 word = None 304 # We are not processing a double-quoted string. 305 in_double_quoted_string = 0 306 # Nor are we processing a brace-quoted string. 307 in_brace_quoted_string = 0 308 # Iterate through all of the characters in s. 309 n = 0 310 while n < len(s): 311 # See what the next character is. 312 c = s[n] 313 # A "$" indicates variable substitution. 314 if c == "$" and not in_brace_quoted_string: 315 k = n + 1 316 if s[k] == "{": 317 # The name of the variable is enclosed in braces. 318 start = k + 1 319 finish = s.index("}", start) 320 n = finish + 1 321 var = s[start:finish] 322 v = variables[var] 323 else: 324 # The following letters, numbers, and underscores make 325 # up the variable name. 326 start = k 327 while (k < len(s) 328 and (s[k].isalnum() or s[k] == "_")): 329 k += 1 330 n = k 331 finish = k 332 if start < finish: 333 var = s[start:finish] 334 v = variables[var] 335 else: 336 v = "$" 337 if word is None: 338 word = v 339 else: 340 word += v 341 continue 342 # A "[" indicates command substitution. 343 elif (c == "[" and not in_brace_quoted_string 344 and n < len(s) + 1 and s[n + 1] != "]"): 345 raise QMException, "Tcl command substitution is unsupported." 346 # A double-quote indicates the beginning of a double-quoted 347 # string. 348 elif c == '"' and not in_brace_quoted_string: 349 # We are now entering a new double-quoted string, or 350 # leaving the old one. 351 in_double_quoted_string = not in_double_quoted_string 352 # Skip the quote. 353 n += 1 354 # The quote starts the word. 355 if word is None: 356 word = "" 357 # A "{" indicates the beginning of a brace-quoted string. 358 elif c == '{' and not in_double_quoted_string: 359 # If that's not the opening quote, add it to the 360 # string. 361 if in_brace_quoted_string: 362 if word is not None: 363 word = word + "{" 364 else: 365 word = "{" 366 # The quote starts the word. 367 if word is None: 368 word = "" 369 # We are entering a brace-quoted string. 370 in_brace_quoted_string += 1 371 # Skip the brace. 372 n += 1 373 elif c == '}' and in_brace_quoted_string: 374 # Leave the brace quoted string. 375 in_brace_quoted_string -= 1 376 # Skip the brace. 377 n += 1 378 # If that's not the closing quote, add it to the 379 # string. 380 if in_brace_quoted_string: 381 if word is not None: 382 word = word + "}" 383 else: 384 word = "}" 385 # A backslash-newline is translated into a space. 386 elif c == '\\' and len(s) > 1 and s[1] == '\n': 387 # Skip the backslash and the newline. 388 n += 2 389 # Now, skip tabs and spaces. 390 while n < len(s) and (s[n] == ' ' or s[n] == '\t'): 391 n += 1 392 # Now prepend one space. 393 n -= 1 394 s[n] = " " 395 # A backslash indicates backslash-substitution. 396 elif c == '\\' and not in_brace_quoted_string: 397 # There should be a character following the backslash. 398 if len(s) == 1: 399 raise QMException, "Invalid Tcl string." 400 # Skip the backslash. 401 n += 1 402 # See what the next character is. 403 c = s[n] 404 # If it's a control character, use the same character 405 # in Python. 406 if c in ["a", "b", "f", "n", "r", "t", "v"]: 407 c = eval('"\%s"' % c) 408 n += 1 409 # "\x" indicates a hex literal. 410 elif c == "x": 411 if (n < len(s) 412 and s[n + 1] in ["0", "1", "2", "3", "4", "5", 413 "6", "7", "8", "9", "a", "b", 414 "c", "d", "e", "f"]): 415 raise QMException, "Unsupported Tcl escape." 416 n += 1 417 # "\d" where "d" is a digit indicates an octal literal. 418 elif c.isdigit(): 419 raise QMException, "Unsupported Tcl escape." 420 # Any other character just indicates the character 421 # itself. 422 else: 423 n += 1 424 # Add it to the current word. 425 if word is not None: 426 word = word + c 427 else: 428 word = c 429 # A space or tab indicates a word separator. 430 elif ((c == ' ' or c == '\t') 431 and not in_double_quoted_string 432 and not in_brace_quoted_string): 433 # Add the current word to the list of words. 434 if word is not None: 435 words.append(word) 436 # Skip over the space. 437 n += 1 438 # Keep skipping while the leading character of s is 439 # a space or tab. 440 while n < len(s) and (s[n] == ' ' or s[n] == '\t'): 441 n += 1 442 # Start the next word. 443 word = None 444 # Any other character is just added to the current word. 445 else: 446 if word is not None: 447 word = word + c 448 else: 449 word = c 450 n += 1 451 452 # If we were working on a word when we reached the end of 453 # the string, add it to the list. 454 if word is not None: 455 words.append(word) 456 457 return words
458

qmtest-2.4.1/share/doc/qmtest/html/manual/random.WichmannHill-class.html0000664000076400007640000005263711122067151025632 0ustar stefanstefan random.WichmannHill
random :: WichmannHill :: Class WichmannHill
[hide private]
[frames] | no frames]

Class WichmannHill

source code

    object --+        
             |        
_random.Random --+    
                 |    
            Random --+
                     |
                    WichmannHill

Instance Methods [hide private]
 
__whseed(self, x=0, y=0, z=0)
Set the Wichmann-Hill seed from (x, y, z).
source code
tuple containing the current state.
getstate(self)
Return internal state; can be passed to setstate() later.
source code
None
jumpahead(self, n)
Act as if n calls to random() were made, but quickly.
source code
x in the interval [0, 1).
random(self)
Get the next random number in the range [0.0, 1.0).
source code
None
seed(self, a=None)
Initialize internal state from hashable object.
source code
None
setstate(self, state)
Restore internal state from object returned by getstate().
source code
 
whseed(self, a=None)
Seed from hashable object's hash code.
source code

Inherited from Random: __getstate__, __init__, __reduce__, __setstate__, betavariate, choice, expovariate, gammavariate, gauss, lognormvariate, normalvariate, paretovariate, randint, randrange, sample, shuffle, uniform, vonmisesvariate, weibullvariate

Inherited from Random (private): _randbelow

Inherited from _random.Random: __getattribute__, __new__, getrandbits

Inherited from object: __delattr__, __hash__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  VERSION = 1
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__whseed(self, x=0, y=0, z=0)

source code 

Set the Wichmann-Hill seed from (x, y, z).

These must be integers in the range [0, 256).

getstate(self)

source code 

Return internal state; can be passed to setstate() later.

Returns: tuple containing the current state.
Overrides: _random.Random.getstate

jumpahead(self, n)

source code 
Act as if n calls to random() were made, but quickly.

n is an int, greater than or equal to 0.

Example use:  If you have 2 threads and know that each will
consume no more than a million random numbers, create two Random
objects r1 and r2, then do
    r2.setstate(r1.getstate())
    r2.jumpahead(1000000)
Then r1 and r2 will use guaranteed-disjoint segments of the full
period.

Returns: None
Overrides: _random.Random.jumpahead

random(self)

source code 

Get the next random number in the range [0.0, 1.0).

Returns: x in the interval [0, 1).
Overrides: _random.Random.random

seed(self, a=None)

source code 

Initialize internal state from hashable object.

None or no argument seeds from current time or from an operating system specific randomness source if available.

If a is not None or an int or long, hash(a) is used instead.

If a is an int or long, a is used directly. Distinct values between 0 and 27814431486575L inclusive are guaranteed to yield distinct internal states (this guarantee is specific to the default Wichmann-Hill generator).

Returns: None
Overrides: _random.Random.seed

setstate(self, state)

source code 

Restore internal state from object returned by getstate().

Returns: None
Overrides: _random.Random.setstate

whseed(self, a=None)

source code 

Seed from hashable object's hash code.

None or no argument seeds from current time. It is not guaranteed that objects with distinct hash codes lead to distinct internal states.

This is obsolete, provided for compatibility with the seed routine used prior to Python 2.1. Use the .seed() method instead.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database-module.html0000664000076400007640000004367311122067145025317 0ustar stefanstefan qm.test.database
Package qm :: Package test :: Module database
[hide private]
[frames] | no frames]

Module database

source code

Classes [hide private]
  ItemDescriptor
An 'ItemDescriptor' describes a test, resource, or similar entity.
  TestDescriptor
A test instance.
  ResourceDescriptor
A resource instance.
  DatabaseError
An exception relating to a 'Database'.
  NoSuchItemError
An exception indicating that a particular item could not be found.
  NoSuchTestError
The specified test does not exist.
  NoSuchSuiteError
The specified suite does not exist.
  NoSuchResourceError
The specified resource does not exist.
  Database
A 'Database' stores tests, testsuites, and resources.
Functions [hide private]
 
get_configuration_directory(path)
Return the configuration directory for the 'Database' rooted at 'path'.
source code
 
get_configuration_file(path)
Return the configuration file for the 'Database' rooted at 'path'.
source code
 
is_database(db_path)
Returns true if 'db_path' looks like a test database.
source code
 
load_database(db_path)
Load the database from 'db_path'.
source code
 
set_path(path)
Set the database path to be used when the database is loaded.
source code
 
get_database()
Returns the global Database object.
source code
Variables [hide private]
  __the_database = None
The global 'Database' object.
  __the_db_path = '.'
The path to the database.
Function Details [hide private]

get_configuration_directory(path)

source code 

Return the configuration directory for the 'Database' rooted at 'path'.

'path' -- The path to the test database.

returns -- The path to the configuration directory.

get_configuration_file(path)

source code 

Return the configuration file for the 'Database' rooted at 'path'.

'path' -- The path to the test database.

returns -- The path to the configuration file.

load_database(db_path)

source code 

Load the database from 'db_path'.

'db_path' -- The path to the directory containing the database.

returns -- The new 'Database'.

set_path(path)

source code 

Set the database path to be used when the database is loaded.

'path' -- A string containing the path to the database.

get_database()

source code 

Returns the global Database object.

returns -- The 'Database' object that corresponds to the currently executing process. It may be None.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_With.With-class.html0000664000076400007640000002102211122067146031704 0ustar stefanstefan qm.external.DocumentTemplate.DT_With.With
Package qm :: Package external :: Package DocumentTemplate :: Module DT_With :: Class With
[hide private]
[frames] | no frames]

Class With

source code

Instance Methods [hide private]
 
__init__(self, blocks) source code
 
render(self, md) source code
 
__call__(self, md) source code
Class Variables [hide private]
  blockContinuations = ()
  name = 'with'
  mapping = None
  only = 0
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Let.Let-class.html0000664000076400007640000001776211122067146031346 0ustar stefanstefan qm.external.DocumentTemplate.DT_Let.Let
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Let :: Class Let
[hide private]
[frames] | no frames]

Class Let

source code

Instance Methods [hide private]
 
__init__(self, blocks) source code
 
render(self, md) source code
 
__call__(self, md) source code
Class Variables [hide private]
  blockContinuations = ()
  name = 'let'
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_String.String-class.html0000664000076400007640000015164611122067146032612 0ustar stefanstefan qm.external.DocumentTemplate.DT_String.String
Package qm :: Package external :: Package DocumentTemplate :: Module DT_String :: Class String
[hide private]
[frames] | no frames]

Class String

source code

Known Subclasses:

Document templates defined from strings.

Document template strings use an extended form of python string formatting. To insert a named value, simply include text of the form: '%(name)x', where 'name' is the name of the value and 'x' is a format specification, such as '12.2d'.

To intrduce a block such as an 'if' or an 'in' or a block continuation, such as an 'else', use '[' as the format specification. To terminate a block, ise ']' as the format specification, as in:

 %(in results)[
   %(name)s
 %(in results)]
Instance Methods [hide private]
 
errQuote(self, s) source code
 
parse_error(self, mess, tag, text, start) source code
 
SubTemplate(self, name) source code
 
tagre(self) source code
 
_parseTag(self, match_ob, command=None, sargs='', tt=<type 'tuple'>) source code
 
parseTag(self, match_ob, command=None, sargs='')
Parse a tag using an already matched re
source code
 
varExtra(self, match_ob) source code
 
parse(self, text, start=0, result=None, tagre=None) source code
 
skip_eol(self, text, start, eol=re.compile(r'[ \t]*\n')) source code
 
parse_block(self, text, start, result, tagre, stag, sloc, sargs, scommand) source code
 
parse_close(self, text, start, tagre, stag, sloc, scommand, sa) source code
 
__init__(self, source_string='', mapping=None, __name__='<string>', **vars)
Create a document template from a string.
source code
 
name(self) source code
 
id(self) source code
 
setName(self, v) source code
 
default(self, name=None, **kw)
Change or query default values in a document template.
source code
 
var(self, name=None, **kw)
Change or query a variable in a document template.
source code
 
munge(self, source_string=None, mapping=None, **vars)
Change the text or default values for a document template.
source code
 
manage_edit(self, data, REQUEST=None) source code
 
read_raw(self, raw=None) source code
 
read(self, raw=None) source code
 
cook(self, cooklock=thread.allocate_lock()) source code
 
initvars(self, globals, vars) source code
 
ZDocumentTemplate_beforeRender(self, md, default) source code
 
ZDocumentTemplate_afterRender(self, md, result) source code
 
__call__(self, client=None, mapping={}, **kw)
Generate a document from a document template.
source code
 
__str__(self) source code
 
__getstate__(self, _special=('_v_', '_p_')) source code
Class Variables [hide private]
  isDocTemp = 1
  func_code = func_code()
  func_defaults__roles__ = ()
  func_defaults = ()
  errQuote__roles__ = ()
  parse_error__roles__ = ()
  commands__roles__ = ()
  commands = {'var': Var, 'call': Call, 'in':('in', 'DT_In', 'In...
  SubTemplate__roles__ = ()
  tagre__roles__ = ()
  _parseTag__roles__ = ()
  parseTag__roles__ = ()
  varExtra__roles__ = ()
  parse__roles__ = ()
  skip_eol__roles__ = ()
  parse_block__roles__ = ()
  parse_close__roles__ = ()
  shared_globals__roles__ = ()
  shared_globals = {}
  setName__roles__ = ()
  default__roles__ = ()
  var__roles__ = ()
  munge__roles__ = ()
  manage_edit__roles__ = ()
  read_raw__roles__ = ()
  read__roles__ = ()
  cook__roles__ = ()
  initvars__roles__ = ()
  ZDocumentTemplate_beforeRender__roles__ = ()
  ZDocumentTemplate_afterRender__roles__ = ()
  validate__roles__ = ()
  validate = None
Method Details [hide private]

parseTag(self, match_ob, command=None, sargs='')

source code 
Parse a tag using an already matched re

Return: tag, args, command, coname

where: tag is the tag,
       args is the tag's argument string,
       command is a corresponding command info structure if the
          tag is a start tag, or None otherwise, and
       coname is the name of a continue tag (e.g. else)
         or None otherwise

__init__(self, source_string='', mapping=None, __name__='<string>', **vars)
(Constructor)

source code 

Create a document template from a string.

The optional parameter, 'mapping', may be used to provide a mapping object containing defaults for values to be inserted.

default(self, name=None, **kw)

source code 

Change or query default values in a document template.

If a name is specified, the value of the named default value before the operation is returned.

Keyword arguments are used to provide default values.

var(self, name=None, **kw)

source code 

Change or query a variable in a document template.

If a name is specified, the value of the named variable before the operation is returned.

Keyword arguments are used to provide variable values.

__call__(self, client=None, mapping={}, **kw)
(Call operator)

source code 
Generate a document from a document template.

The document will be generated by inserting values into the
format string specified when the document template was
created.  Values are inserted using standard python named
string formats.

The optional argument 'client' is used to specify a object
containing values to be looked up.  Values will be looked up
using getattr, so inheritence of values is supported.  Note
that names beginning with '_' will not be looked up from the
client.

The optional argument, 'mapping' is used to specify a mapping
object containing values to be inserted.

Values to be inserted may also be specified using keyword
arguments.

Values will be inserted from one of several sources.  The
sources, in the order in which they are consulted, are:

  o  Keyword arguments,

  o  The 'client' argument,

  o  The 'mapping' argument,

  o  The keyword arguments provided when the object was
     created, and

  o  The 'mapping' argument provided when the template was
     created.


Class Variable Details [hide private]

commands

Value:
{'call': <class qm.external.DocumentTemplate.DT_Var.Call at 0x7f00bc58\
c110>,
 'comment': <class qm.external.DocumentTemplate.DT_Var.Comment at 0x7f\
00bc58c170>,
 'else': ('else', 'DT_If', 'Else'),
 'if': ('if', 'DT_If', 'If'),
 'in': ('in', 'DT_In', 'In'),
 'let': ('let', 'DT_Let', 'Let'),
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.Group-class.html0000664000076400007640000002701611122067151024454 0ustar stefanstefan qm.user.Group
qm :: user :: Group :: Class Group
[hide private]
[frames] | no frames]

Class Group

source code

A group of users.

A 'Group' object is treated as an ordinary list of user IDs (except that a user ID may not appear more than once in the list).

Instance Methods [hide private]
 
__init__(self, group_id, user_ids=[])
Create a new group.
source code
 
GetId(self)
Return the group_id of this group.
source code
 
__len__(self) source code
 
__getitem__(self, index) source code
 
__setitem__(self, index, user_id) source code
 
__delitem__(self, index) source code
 
append(self, user_id) source code
 
remove(self, user_id) source code
Method Details [hide private]

__init__(self, group_id, user_ids=[])
(Constructor)

source code 

Create a new group.

'group_id' -- The ID of this group.

'user_ids' -- IDs of users initially in the group.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.result_reader-module.html0000664000076400007640000000213511122067144027161 0ustar stefanstefan result_reader

Module result_reader


Classes

ResultReader

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_Try-module.html0000664000076400007640000000211311122067144031576 0ustar stefanstefan DT_Try

Module DT_Try


Classes

Try

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.suite-pysrc.html0000664000076400007640000022514711122067161024553 0ustar stefanstefan qm.test.suite
Package qm :: Package test :: Module suite
[hide private]
[frames] | no frames]

Source Code for Module qm.test.suite

  1  ######################################################################## 
  2  # 
  3  # File:   suite.py 
  4  # Author: Mark Mitchell 
  5  # Date:   11/05/2001 
  6  # 
  7  # Contents: 
  8  #   QMTest Suite class 
  9  # 
 10  # Copyright (c) 2001 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  import qm.extension 
 22   
 23  ######################################################################## 
 24  # Classes 
 25  ######################################################################## 
 26   
27 -class Suite(qm.extension.Extension):
28 """A collection of tests. 29 30 A test suite is a collection of tests. The suite may contain other 31 suites by reference as well; all tests contained in these contained 32 suites are considered contained in the containing suite as well.""" 33 34 arguments = [ 35 ] 36 37 kind = "suite" 38 39 EXTRA_ID = "qmtest_id" 40 """The name of the extra keyword argument to '__init__' that 41 specifies the name of the test or resource.""" 42 43 EXTRA_DATABASE = "qmtest_database" 44 """The name of the extra keyword argument to '__init__' that 45 specifies the database containing the test or resource.""" 46 47
48 - def __init__(self, arguments = None, **args):
49 """Construct a new 'Runnable'. 50 51 'arguments' -- As for 'Extension.__init__'. 52 53 'args' -- As for 'Extension.__init__'.""" 54 55 self.__id = args.pop(self.EXTRA_ID) 56 self.__database = args.pop(self.EXTRA_DATABASE) 57 if arguments: args.update(arguments) 58 super(Suite, self).__init__(**args)
59 60 61
62 - def GetDatabase(self):
63 """Return the 'Database' that contains this suite. 64 65 returns -- The 'Database' that contains this suite.""" 66 67 return self.__database
68 69
70 - def GetId(self):
71 """Return the ID of this test suite.""" 72 73 return self.__id
74 75
76 - def GetTestIds(self):
77 """Return the tests contained in this suite. 78 79 returns -- A sequence of labels corresponding to the tests 80 contained in this suite. Tests that are contained in this suite 81 only because they are contained in a suite which is itself 82 contained in this suite are not returned.""" 83 84 return []
85 86
87 - def GetSuiteIds(self):
88 """Return the suites contained in this suite. 89 90 returns -- A sequence of labels corresponding to the suites 91 contained in this suite. Suites that are contained in this suite 92 only because they are contained in a suite which is itself 93 contained in this suite are not returned.""" 94 95 return []
96 97
98 - def IsImplicit(self):
99 """Return true if this is an implicit test suite. 100 101 Implicit test suites cannot be edited.""" 102 103 raise NotImplementedError
104 105
106 - def GetAllTestAndSuiteIds(self):
107 """Return the tests/suites contained in this suite and its subsuites. 108 109 returns -- A pair '(test_ids, suite_ids)'. The 'test_ids' and 110 'suite_ids' elements are both sequences of labels. The values 111 returned include all tests and suites that are contained in this 112 suite and its subsuites, recursively.""" 113 114 suite = self 115 116 test_ids = [] 117 suite_ids = [] 118 119 # Maintain a work list of suites to process. 120 work_list = [suite] 121 # Process until the work list is empty. 122 while len(work_list) > 0: 123 suite = work_list.pop(0) 124 # Accumulate test and resource IDs in the suite. 125 test_ids.extend(suite.GetTestIds()) 126 # Find sub suites in the suite. 127 sub_suite_ids = suite.GetSuiteIds() 128 # Accumulate them. 129 suite_ids.extend(sub_suite_ids) 130 # Retrieve the 'Suite' objects. 131 sub_suites = map(self.GetDatabase().GetSuite, sub_suite_ids) 132 # Don't expand ordinary suites contained in implicit suites. 133 if suite.IsImplicit(): 134 sub_suites = filter(lambda s: s.IsImplicit(), sub_suites) 135 # Add contained suites to the work list. 136 work_list.extend(sub_suites) 137 138 return test_ids, suite_ids
139

././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_InSV.sequence_variables-cl0000664000076400007640000006277411122067146033106 0ustar stefanstefan qm.external.DocumentTemplate.DT_InSV.sequence_variables
Package qm :: Package external :: Package DocumentTemplate :: Module DT_InSV :: Class sequence_variables
[hide private]
[frames] | no frames]

Class sequence_variables

source code

Instance Methods [hide private]
 
__init__(self, items=None, query_string='', start_name_re=None) source code
 
__len__(self) source code
 
number(self, index) source code
 
even(self, index) source code
 
odd(self, index) source code
 
letter(self, index) source code
 
Letter(self, index) source code
 
key(self, index) source code
 
item(self, index, tt=<type 'tuple'>) source code
 
roman(self, index) source code
 
Roman(self, num) source code
 
value(self, index, name) source code
 
first(self, name, key='') source code
 
last(self, name, key='') source code
 
length(self, ignored) source code
 
query(self, *ignored) source code
 
statistics(self, name, key) source code
 
next_batches(self, suffix='batches', key='') source code
 
previous_batches(self, suffix='batches', key='') source code
 
__getitem__(self, key, special_prefixes=special_prefixes, special_prefix=<built-in method has_key of dict object at 0x7f00bbbd8640>) source code
Class Variables [hide private]
  statistic_names = ('total', 'count', 'min', 'max', 'median', '...
  special_prefixes = special_prefixes
  n = 'standard-deviation-n'
Class Variable Details [hide private]

statistic_names

Value:
('total',
 'count',
 'min',
 'max',
 'median',
 'mean',
 'variance',
 'variance-n',
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.DefaultAuthenticator-class.html0000664000076400007640000002146311122067151027477 0ustar stefanstefan qm.user.DefaultAuthenticator
qm :: user :: DefaultAuthenticator :: Class DefaultAuthenticator
[hide private]
[frames] | no frames]

Class DefaultAuthenticator

source code

Authenticator --+
                |
               DefaultAuthenticator

Authenticator for only a single user, "default_user".

Instance Methods [hide private]
 
AuthenticateDefaultUser(self)
Authenticate for the default user, if one is provided.
source code
 
AuthenticateWebRequest(self, request)
Authenticate a login web request.
source code
Method Details [hide private]

AuthenticateDefaultUser(self)

source code 

Authenticate for the default user, if one is provided.

returns -- The user ID of the default user.

Overrides: Authenticator.AuthenticateDefaultUser
(inherited documentation)

AuthenticateWebRequest(self, request)

source code 

Authenticate a login web request.

'request' -- A web request containing the user's login information.

returns -- The user ID of the authenticated user.

Overrides: Authenticator.AuthenticateWebRequest
(inherited documentation)

././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate.DictInstance-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate.DictInstanc0000664000076400007640000001405511122067146033266 0ustar stefanstefan qm.external.DocumentTemplate.pDocumentTemplate.DictInstance
Package qm :: Package external :: Package DocumentTemplate :: Module pDocumentTemplate :: Class DictInstance
[hide private]
[frames] | no frames]

Class DictInstance

source code

Instance Methods [hide private]
 
__init__(self, mapping) source code
 
__getattr__(self, name) source code
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.UploadAttachmentPage-class.html0000664000076400007640000003047011122067146027704 0ustar stefanstefan qm.fields.UploadAttachmentPage
qm :: fields :: UploadAttachmentPage :: Class UploadAttachmentPage
[hide private]
[frames] | no frames]

Class UploadAttachmentPage

source code

web.DtmlPage --+
               |
              UploadAttachmentPage

DTML context for generating upload-attachment.dtml.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, attachment_store, field_name, encoding_name, summary_field_name, in_set=0)
Create a new page object.
source code
 
MakeSubmitUrl(self)
Return the URL for submitting this form.
source code

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateHtmlHeader, GenerateStartBody, GenerateStartScript, GenerateXMLHeader, GetMainPageUrl, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, attachment_store, field_name, encoding_name, summary_field_name, in_set=0)
(Constructor)

source code 

Create a new page object.

'attachment_store' -- The AttachmentStore in which the new attachment will be placed.

'field_name' -- The user-visible name of the field for which an attachment is being uploaded.

'encoding_name' -- The name of the HTML input that should contain the encoded attachment.

'summary_field_name' -- The name of the HTML input that should contain the user-visible summary of the attachment.

'in_set' -- If true, the attachment is being added to an attachment set field.

Overrides: web.DtmlPage.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_UI-pysrc.html0000664000076400007640000004734211122067153030442 0ustar stefanstefan qm.external.DocumentTemplate.DT_UI
Package qm :: Package external :: Package DocumentTemplate :: Module DT_UI
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_UI

 1  ############################################################################## 
 2  # 
 3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
 4  # 
 5  # This software is subject to the provisions of the Zope Public License, 
 6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
 7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
 8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
10  # FOR A PARTICULAR PURPOSE 
11  # 
12  ############################################################################## 
13  __doc__='''Machinery to support through-the-web editing 
14   
15  $Id: DT_UI.py 1069 2008-11-13 21:55:43Z stefan $''' 
16  __version__='$Revision: 1069 $'[11:-2] 
17   
18  from DT_HTML import HTML 
19   
20  FactoryDefaultString="Factory Default" 
21   
22  HTML.document_template_edit_header='<h2>Edit Document</h2>' 
23  HTML.document_template_form_header='' 
24  HTML.document_template_edit_footer=( 
25      """<FONT SIZE="-1"> 
26      <I><A HREF="http://www.zope.com"> 
27      &copy; 2002 Zope Corporation</A></I></FONT>""") 
28  HTML._manage_editForm = HTML( 
29      """<HTML> 
30      <HEAD> 
31      <TITLE>HTML Template Editor</TITLE> 
32      </HEAD> 
33      <BODY bgcolor="#FFFFFF"> 
34      <!--#var document_template_edit_header--> 
35       
36      <FORM name="editform" ACTION="<!--#var URL1-->/manage_edit" METHOD="POST"> 
37      <!--#var document_template_form_header--> 
38      Document template source: 
39      <center> 
40      <br> 
41      <TEXTAREA NAME="data:text" cols="<!--#var document_template_edit_width-->"  
42                      rows="20"><!--#var __str__--></TEXTAREA> 
43   
44      <br> 
45        <INPUT NAME=SUBMIT TYPE="SUBMIT" VALUE="Change"> 
46        <INPUT NAME=SUBMIT TYPE="RESET"  VALUE="Reset"> 
47        <INPUT NAME="dt_edit_name" TYPE="HIDDEN" 
48               VALUE="<!--#var URL1-->"> 
49        <!--#if FactoryDefaultString--> 
50          <INPUT NAME=SUBMIT TYPE="SUBMIT"  
51           VALUE="<!--#var FactoryDefaultString-->"> 
52        <!--#/if FactoryDefaultString--> 
53        <INPUT NAME=SUBMIT TYPE="SUBMIT" VALUE="Cancel"> 
54        <!--#if HTTP_REFERER--> 
55           <INPUT NAME="CANCEL_ACTION" TYPE="HIDDEN"  
56                  VALUE="<!--#var HTTP_REFERER-->"> 
57        <!--#else HTTP_REFERER--> 
58           <!--#if URL1--> 
59             <INPUT NAME="CANCEL_ACTION" TYPE="HIDDEN" 
60                    VALUE="<!--#var URL1-->"> 
61           <!--#/if URL1--> 
62        <!--#/if HTTP_REFERER--> 
63      </center> 
64      </FORM> 
65   
66      <BR CLEAR="ALL"> 
67      <!--#var document_template_edit_footer--> 
68   
69      </BODY> 
70      </HTML>""",) 
71   
72  HTML.editConfirmation=HTML( 
73      """<html><head><title>Change Successful</title></head><body> 
74      <!--#if CANCEL_ACTION--> 
75        <form action="<!--#var CANCEL_ACTION-->" method="POST"> 
76          <center> 
77             <em><!--#var dt_edit_name--></em><br>has been changed.<br><br> 
78             <input type=submit name="SUBMIT" value="OK"> 
79          </center> 
80        </form></body></html> 
81      <!--#else CANCEL_ACTION--> 
82        <center> 
83           <em><!--#var dt_edit_name--></em><br>has been changed. 
84        </center> 
85      <!--#/if CANCEL_ACTION-->""") 
86   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test_run-pysrc.html0000664000076400007640000010255111122067162025257 0ustar stefanstefan qm.test.test_run
Package qm :: Package test :: Module test_run
[hide private]
[frames] | no frames]

Source Code for Module qm.test.test_run

  1  ######################################################################## 
  2  # 
  3  # File:   test_run.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2005-08-08 
  6  # 
  7  # Contents: 
  8  #   QMTest TestRun class. 
  9  # 
 10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  from qm.test.result import Result 
 21   
 22  ######################################################################## 
 23  # Classes 
 24  ######################################################################## 
 25   
26 -class TestRun(object):
27 """A 'TestRun' stores the 'Result's from a single test run. 28 29 The primary contents of a 'TestRun' are the the 'Result's of the 30 run. In addition, each 'TestRun' has an associated set of 31 annotations, which are used to store global information about the 32 'TestRun'.""" 33
34 - def GetResult(self, id, kind = Result.TEST):
35 """Return the 'Result' for the indicated test. 36 37 'id' -- The name of a test or resource. 38 39 'kind' -- The kind of result to retrieve. See 'Result' for a 40 list of the available result kinds. 41 42 returns -- The 'Result' corresponding to 'test_id'. 43 44 raises -- 'KeyError' if there is no result of the given 'kind' 45 for 'id' in the test run.""" 46 47 raise NotImplementedError
48 49
50 - def GetAnnotation(self, key):
51 """Return the annotation associated with 'key'. 52 53 'key' -- A string giving the name of an annotation. 54 55 returns -- A string giving the value of the annotation, or 56 'None' if there is no such annotation.""" 57 58 raise NotImplementedError
59 60
61 - def GetAnnotations(self):
62 """Return this run's dictionary of annotations. 63 64 returns -- A dictionary mapping annotation names (strings) to values 65 (also strings).""" 66 67 raise NotImplementedError
68 69
70 - def GetAllResults(self, directory = "", kind = Result.TEST):
71 """Return 'Result's from the given directory.. 72 73 'directory' -- A path to a directory in the test database. 74 75 'kind' -- The kind of results to return. 76 77 returns -- All the results within 'directory' (including its 78 subdirectories).""" 79 80 raise NotImplementedError
81 82
83 - def GetResultsByOutcome(self, outcome = None, directory = "", 84 kind = Result.TEST):
85 """Return 'Result's with a particular outcome. 86 87 'outcome' -- One of the 'Result.outcomes', or 'None'. 88 89 'directory' -- A path to a directory in the test database. 90 91 'kind' -- The kind of results to return. 92 93 returns -- All the results within 'directory' (including its 94 subdirectories) that have the indicated 'outcome', or, if 95 'outcome' is 'None', all test results from 'directory'.""" 96 97 results = [] 98 for result in self.GetAllResults(directory, kind): 99 # Check the outcome. 100 if outcome and result.GetOutcome() != outcome: 101 continue 102 results.append(result) 103 return results
104 105
106 - def CountOutcomes(self, directory = "", outcome = None):
107 """Return statistics about the outcomes of tests. 108 109 'directory' -- A path to a directory in the test database. 110 111 'outcome' -- If not 'None', one of the 'Result.outcomes'. 112 113 returns -- A dictionary mapping outcomes to the number of test 114 results with that outcome located within 'directory' and its 115 subdirectories. If 'outcome' is not 'None', the dictionary 116 will have an entry only for the 'outcome' specified.""" 117 118 if not outcome: 119 outcomes = Result.outcomes 120 else: 121 outcomes = (outcome,) 122 counts = {} 123 for o in outcomes: 124 counts[o] = len(self.GetResultsByOutcome(o, directory)) 125 return counts
126

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.xmlutil-module.html0000664000076400007640000000522111122067145025041 0ustar stefanstefan xmlutil

Module xmlutil


Functions

child_tag_predicate
create_dom_document
create_dom_text_element
get_child
get_child_text
get_child_texts
get_dom_text
load_xml
load_xml_file
make_public_id
make_system_id
sanitize_text_for_comment

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_result_stream-pysrc.html0000664000076400007640000016346511122067153027317 0ustar stefanstefan qm.test.file_result_stream
Package qm :: Package test :: Module file_result_stream
[hide private]
[frames] | no frames]

Source Code for Module qm.test.file_result_stream

 1  ######################################################################## 
 2  # 
 3  # File:   file_result_stream.py 
 4  # Author: Mark Mitchell 
 5  # Date:   04/13/2003 
 6  # 
 7  # Contents: 
 8  #   FileResultStream 
 9  # 
10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ######################################################################## 
17   
18  import qm.common 
19  import qm.fields 
20  from   qm.test.result_stream import ResultStream 
21  import sys 
22   
23  ######################################################################## 
24  # Classes 
25  ######################################################################## 
26   
27 -class FileResultStream(ResultStream):
28 """A 'FileResultStream' writes its output to a file. 29 30 A 'FileResultStream' is an abstract base class for other result 31 stream classes that store results in a single file. The file to 32 which results should be written can be specified using either the 33 'filename' argument or the 'file' argument. The latter is for use 34 by QMTest internally.""" 35 36 arguments = [ 37 qm.fields.TextField( 38 name = "filename", 39 title = "File Name", 40 description = """The name of the file. 41 42 All results will be written to the file indicated. If no 43 filename is specified, or the filename specified is "-", 44 the standard output will be used.""", 45 verbatim = "true", 46 default_value = ""), 47 qm.fields.PythonField( 48 name = "file"), 49 ] 50 51 _is_binary_file = 0 52 """If true, the file written is a binary file. 53 54 This flag can be overridden by derived classes.""" 55
56 - def __init__(self, arguments = None, **args):
57 58 ResultStream.__init__(self, arguments, **args) 59 60 if not self.file: 61 if self.filename and self.filename != "-": 62 # Open the file in unbuffered mode so that results will be 63 # written out immediately. 64 if self._is_binary_file: 65 mode = "wb" 66 else: 67 mode = "w" 68 self.file = open(self.filename, mode, 0) 69 # Child processes do not need to write to the results 70 # file. 71 qm.common.close_file_on_exec(self.file) 72 else: 73 self.file = sys.stdout
74

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform_win32-pysrc.html0000664000076400007640000005741711122067155025320 0ustar stefanstefan qm.platform_win32
Package qm :: Module platform_win32
[hide private]
[frames] | no frames]

Source Code for Module qm.platform_win32

  1  ######################################################################## 
  2  # 
  3  # File:   platform_win32.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-05-13 
  6  # 
  7  # Contents: 
  8  #   Platform-specific function for Win32. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import common 
 21  import os 
 22  import qm 
 23  import signal 
 24  import string 
 25  import sys 
 26   
 27  ######################################################################## 
 28  # constants 
 29  ######################################################################## 
 30   
 31  default_shell = [os.environ.get("COMSPEC", r"C:\WINNT\SYSTEM32\CMD.EXE")] 
 32   
 33  ######################################################################## 
 34  # classes 
 35  ######################################################################## 
 36   
 37  # Win32 doesn't provide signals, but we include this anyway so that code 
 38  # may attempt to catch this exception without conditionalizing. 
 39   
40 -class SignalException(Exception):
41
42 - def __init__(self, *args):
43 raise NotImplementedError, "No 'SignalException' on Win32."
44 45 46 47 ######################################################################## 48 # functions 49 ######################################################################## 50
51 -def get_host_name():
52 """Return the name of this computer.""" 53 54 # This function caches the result of '_get_host_name' by replacing 55 # itself with a lambda that returns the cached value. 56 global get_host_name 57 get_host_name = lambda host_name=_get_host_name(): host_name
58 59
60 -def _get_host_name():
61 """Return the name of this computer.""" 62 63 # First try to look up our own address in DNS. 64 try: 65 return socket.gethostbyname_ex(socket.gethostname())[0] 66 except socket.error: 67 pass 68 69 # That didn't work. Just use the local name. 70 try: 71 return socket.gethostname() 72 except socket.error: 73 pass 74 75 # That didn't work either. Check if the host name is stored in the 76 # environment. 77 try: 78 return os.environ["HOSTNAME"] 79 except KeyError: 80 pass 81 82 # We're stumped. Use something dumb. 83 return "localhost"
84 85
86 -def open_in_browser(url):
87 """Open a browser window and point it at 'url'. 88 89 The browser is run in a separate, independent process.""" 90 91 os.startfile(url)
92 93 94 ######################################################################## 95 # Local Variables: 96 # mode: python 97 # indent-tabs-mode: nil 98 # fill-column: 72 99 # End: 100

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.NewItemPage-class.html0000664000076400007640000004354311122067151027061 0ustar stefanstefan qm.test.web.web.NewItemPage
Package qm :: Package test :: Package web :: Module web :: Class NewItemPage
[hide private]
[frames] | no frames]

Class NewItemPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      NewItemPage

Page for creating a new test or resource.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, type, item_id="", class_name="", field_errors={})
Create a new DTML context.
source code
 
GetTitle(self)
Return the title this page.
source code
 
GetClassDescriptions(self)
Return a description of the available classes.
source code
 
MakeSubmitUrl(self)
Return the URL for submitting the form.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, type, item_id="", class_name="", field_errors={})
(Constructor)

source code 

Create a new DTML context.

'type' -- Either "test" or "resource".

'server' -- The 'QMTestServer' creating this page.

'item_id' -- The item ID to show.

'class_name' -- The class name to show.

'field_errors' -- A mapping of error messages for fields. Keys may be "_id" or "_class".

Overrides: web.DtmlPage.__init__

GetClassDescriptions(self)

source code 

Return a description of the available classes.

returns -- Structured text describing each of the available test or resource classes.

MakeSubmitUrl(self)

source code 

Return the URL for submitting the form.

The URL is for the script 'create-test' or 'create-resource' as appropriate.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler.SourcePosition-class.html0000664000076400007640000002224511122067147031617 0ustar stefanstefan qm.test.classes.compiler.SourcePosition
Package qm :: Package test :: Package classes :: Module compiler :: Class SourcePosition
[hide private]
[frames] | no frames]

Class SourcePosition

source code

A 'SourcePosition' indicates a location in source code.

A 'SourcePosition' consists of:

- A file name.  The file name is a string.  It may be an absolute
  or relative path.  If no file name is available, the file name
  is the empty string.

- A line number, indexed from one.  If no line number is
  available, the line number is zero.

- A column number, indexed from one.  If no column number is
  available, the column nubmer is zero.

Instance Methods [hide private]
 
__init__(self, file, line, column)
Construct a new 'SourcePosition'.
source code
 
__str__(self)
Return a textual representation of this 'SourcePosition'.
source code
Method Details [hide private]

__init__(self, file, line, column)
(Constructor)

source code 

Construct a new 'SourcePosition'.

'file' -- The file name.

'line' -- The line number, indexed from one. If no line numer is availble, use zero for this parameter.

'column' -- The column number, indexed from one. If no column number is available, use zero for this parameter.

__str__(self)
(Informal representation operator)

source code 

Return a textual representation of this 'SourcePosition'.

returns -- A string representing this 'SourcePosition'


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.cmdline-pysrc.html0000664000076400007640000242770211122067160025037 0ustar stefanstefan qm.test.cmdline
Package qm :: Package test :: Module cmdline
[hide private]
[frames] | no frames]

Source Code for Module qm.test.cmdline

   1  ######################################################################## 
   2  # 
   3  # File:   cmdline.py 
   4  # Author: Alex Samuel 
   5  # Date:   2001-03-16 
   6  # 
   7  # Contents: 
   8  #   QMTest command processing 
   9  # 
  10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
  11  # 
  12  # For license terms see the file COPYING. 
  13  # 
  14  ######################################################################## 
  15   
  16  ######################################################################## 
  17  # Imports 
  18  ######################################################################## 
  19   
  20  import base 
  21  import database 
  22  import os 
  23  import qm 
  24  import qm.attachment 
  25  import qm.cmdline 
  26  import qm.platform 
  27  from   qm.extension import get_extension_class_name, get_class_description 
  28  from   qm.test import test 
  29  from   qm.test.result import Result 
  30  from   qm.test.context import * 
  31  from   qm.test.execution_engine import * 
  32  from   qm.test.result_stream import ResultStream 
  33  from   qm.test.runnable import Runnable 
  34  from   qm.test.suite import Suite 
  35  from   qm.test.report import ReportGenerator 
  36  from   qm.test.classes.dir_run_database import * 
  37  from   qm.test.expectation_database import ExpectationDatabase 
  38  from   qm.test.classes.previous_testrun import PreviousTestRun 
  39  from   qm.trace import * 
  40  from   qm.test.web.web import QMTestServer 
  41  import qm.structured_text 
  42  import qm.xmlutil 
  43  import Queue 
  44  import random 
  45  from   result import * 
  46  import signal 
  47  import string 
  48  import sys 
  49  import xml.sax 
  50   
  51  ######################################################################## 
  52  # Variables 
  53  ######################################################################## 
  54   
  55  _the_qmtest = None 
  56  """The global 'QMTest' object.""" 
  57   
  58  ######################################################################## 
  59  # Functions 
  60  ######################################################################## 
  61   
62 -def _make_comma_separated_string (items, conjunction):
63 """Return a string consisting of the 'items', separated by commas. 64 65 'items' -- A list of strings giving the items in the list. 66 67 'conjunction' -- A string to use before the final item, if there is 68 more than one. 69 70 returns -- A string consisting all of the 'items', separated by 71 commas, and with the 'conjunction' before the final item.""" 72 73 s = "" 74 need_comma = 0 75 # Go through almost all of the items, adding them to the 76 # comma-separated list. 77 for i in items[:-1]: 78 # Add a comma if this isn't the first item in the list. 79 if need_comma: 80 s += ", " 81 else: 82 need_comma = 1 83 # Add this item. 84 s += "'%s'" % i 85 # The last item is special, because we need to include the "or". 86 if items: 87 i = items[-1] 88 if need_comma: 89 s += ", %s " % conjunction 90 s += "'%s'" % i 91 92 return s
93 94 ######################################################################## 95 # Classes 96 ######################################################################## 97
98 -class QMTest:
99 """An instance of QMTest.""" 100 101 __extension_kinds_string \ 102 = _make_comma_separated_string(base.extension_kinds, "or") 103 """A string listing the available extension kinds.""" 104 105 db_path_environment_variable = "QMTEST_DB_PATH" 106 """The environment variable specifying the test database path.""" 107 108 summary_formats = ("brief", "full", "stats", "batch", "none") 109 """Valid formats for result summaries.""" 110 111 context_file_name = "context" 112 """The default name of a context file.""" 113 114 expectations_file_name = "expectations.qmr" 115 """The default name of a file containing expectations.""" 116 117 results_file_name = "results.qmr" 118 """The default name of a file containing results.""" 119 120 target_file_name = "targets" 121 """The default name of a file containing targets.""" 122 123 help_option_spec = ( 124 "h", 125 "help", 126 None, 127 "Display usage summary." 128 ) 129 130 version_option_spec = ( 131 None, 132 "version", 133 None, 134 "Display version information." 135 ) 136 137 db_path_option_spec = ( 138 "D", 139 "tdb", 140 "PATH", 141 "Path to the test database." 142 ) 143 144 extension_output_option_spec = ( 145 "o", 146 "output", 147 "FILE", 148 "Write the extension to FILE.", 149 ) 150 151 extension_id_option_spec = ( 152 "i", 153 "id", 154 "NAME", 155 "Write the extension to the database as NAME.", 156 ) 157 158 output_option_spec = ( 159 "o", 160 "output", 161 "FILE", 162 "Write test results to FILE (- for stdout)." 163 ) 164 165 no_output_option_spec = ( 166 None, 167 "no-output", 168 None, 169 "Don't generate test results." 170 ) 171 172 outcomes_option_spec = ( 173 "O", 174 "outcomes", 175 "FILE", 176 "Use expected outcomes in FILE." 177 ) 178 179 expectations_option_spec = ( 180 "e", 181 "expectations", 182 "FILE", 183 "Use expectations in FILE." 184 ) 185 186 context_option_spec = ( 187 "c", 188 "context", 189 "KEY=VALUE", 190 "Add or override a context property." 191 ) 192 193 context_file_spec = ( 194 "C", 195 "load-context", 196 "FILE", 197 "Read context from a file (- for stdin)." 198 ) 199 200 daemon_option_spec = ( 201 None, 202 "daemon", 203 None, 204 "Run as a daemon." 205 ) 206 207 port_option_spec = ( 208 "P", 209 "port", 210 "PORT", 211 "Server port number." 212 ) 213 214 address_option_spec = ( 215 "A", 216 "address", 217 "ADDRESS", 218 "Local address." 219 ) 220 221 log_file_option_spec = ( 222 None, 223 "log-file", 224 "PATH", 225 "Log file name." 226 ) 227 228 no_browser_option_spec = ( 229 None, 230 "no-browser", 231 None, 232 "Do not open a new browser window." 233 ) 234 235 pid_file_option_spec = ( 236 None, 237 "pid-file", 238 "PATH", 239 "Process ID file name." 240 ) 241 242 concurrent_option_spec = ( 243 "j", 244 "concurrency", 245 "COUNT", 246 "Execute tests in COUNT concurrent threads." 247 ) 248 249 targets_option_spec = ( 250 "T", 251 "targets", 252 "FILE", 253 "Use FILE as the target specification file." 254 ) 255 256 random_option_spec = ( 257 None, 258 "random", 259 None, 260 "Run the tests in a random order." 261 ) 262 263 rerun_option_spec = ( 264 None, 265 "rerun", 266 "FILE", 267 "Rerun the tests that failed." 268 ) 269 270 seed_option_spec = ( 271 None, 272 "seed", 273 "INTEGER", 274 "Seed the random number generator." 275 ) 276 277 format_option_spec = ( 278 "f", 279 "format", 280 "FORMAT", 281 "Specify the summary format." 282 ) 283 284 result_stream_spec = ( 285 None, 286 "result-stream", 287 "CLASS-NAME", 288 "Specify the results file format." 289 ) 290 291 annotation_option_spec = ( 292 "a", 293 "annotate", 294 "NAME=VALUE", 295 "Set an additional annotation to be written to the result stream(s)." 296 ) 297 298 tdb_class_option_spec = ( 299 "c", 300 "class", 301 "CLASS-NAME", 302 "Specify the test database class.", 303 ) 304 305 attribute_option_spec = ( 306 "a", 307 "attribute", 308 "NAME", 309 "Get an attribute of the extension class." 310 ) 311 312 set_attribute_option_spec = ( 313 "a", 314 "attribute", 315 "KEY=VALUE", 316 "Set an attribute of the extension class." 317 ) 318 319 extension_kind_option_spec = ( 320 "k", 321 "kind", 322 "EXTENSION-KIND", 323 "Specify the kind of extension class." 324 ) 325 326 report_output_option_spec = ( 327 "o", 328 "output", 329 "FILE", 330 "Write test report to FILE (- for stdout)." 331 ) 332 333 report_flat_option_spec = ( 334 "f", 335 "flat", 336 None, 337 """Generate a flat listing of test results, instead of reproducing the 338 database directory tree in the report.""" 339 ) 340 341 results_option_spec = ( 342 "R", 343 "results", 344 "DIRECTORY", 345 "Read in all results (*.qmr) files from DIRECTORY." 346 ) 347 348 list_long_option_spec = ( 349 "l", 350 "long", 351 None, 352 "Use a detailed output format." 353 ) 354 355 list_details_option_spec = ( 356 "d", 357 "details", 358 None, 359 "Display details for individual items." 360 ) 361 362 list_recursive_option_spec = ( 363 "R", 364 "recursive", 365 None, 366 "Recursively list the contents of directories." 367 ) 368 369 # Groups of options that should not be used together. 370 conflicting_option_specs = ( 371 ( output_option_spec, no_output_option_spec ), 372 ( concurrent_option_spec, targets_option_spec ), 373 ( extension_output_option_spec, extension_id_option_spec ), 374 ( expectations_option_spec, outcomes_option_spec ), 375 ) 376 377 global_options_spec = [ 378 help_option_spec, 379 version_option_spec, 380 db_path_option_spec, 381 ] 382 383 commands_spec = [ 384 ("create", 385 "Create (or update) an extension.", 386 "EXTENSION-KIND CLASS-NAME(ATTR1 = 'VAL1', ATTR2 = 'VAL2', ...)", 387 """Create (or update) an extension. 388 389 The EXTENSION-KIND indicates what kind of extension to 390 create; it must be one of """ + __extension_kinds_string + """. 391 392 The CLASS-NAME indicates the name of the extension class, or 393 the name of an existing extension object. If the CLASS-NAME 394 is the name of a extension in the test database, then the 395 396 In the former case, it must have the form 'MODULE.CLASS'. For 397 a list of available extension classes use "qmtest extensions". 398 If the extension class takes arguments, those arguments can be 399 specified after the CLASS-NAME as show above. In the latter 400 case, 401 402 Any "--attribute" options are processed before the arguments 403 specified after the class name. Therefore, the "--attribute" 404 options can be overridden by the arguments provided after the 405 CLASS-NAME. If no attributes are specified, the parentheses 406 following the 'CLASS-NAME' can be omitted. 407 408 If the "--id" option is given, the extension is written to the 409 database. Otherwise, if the "--output" option is given, the 410 extension is written as XML to the file indicated. If neither 411 option is given, the extension is written as XML to the 412 standard output.""", 413 ( set_attribute_option_spec, 414 help_option_spec, 415 extension_id_option_spec, 416 extension_output_option_spec 417 ), 418 ), 419 420 ("create-target", 421 "Create (or update) a target specification.", 422 "NAME CLASS [ GROUP ]", 423 "Create (or update) a target specification.", 424 ( set_attribute_option_spec, 425 help_option_spec, 426 targets_option_spec 427 ) 428 ), 429 430 ("create-tdb", 431 "Create a new test database.", 432 "", 433 "Create a new test database.", 434 ( help_option_spec, 435 tdb_class_option_spec, 436 set_attribute_option_spec) 437 ), 438 439 ("gui", 440 "Start the QMTest GUI.", 441 "", 442 "Start the QMTest graphical user interface.", 443 ( 444 address_option_spec, 445 concurrent_option_spec, 446 context_file_spec, 447 context_option_spec, 448 daemon_option_spec, 449 help_option_spec, 450 log_file_option_spec, 451 no_browser_option_spec, 452 pid_file_option_spec, 453 port_option_spec, 454 outcomes_option_spec, 455 targets_option_spec, 456 results_option_spec 457 ) 458 ), 459 460 ("extensions", 461 "List extension classes.", 462 "", 463 """ 464 List the available extension classes. 465 466 Use the '--kind' option to limit the classes displayed to test classes, 467 resource classes, etc. The parameter to '--kind' can be one of """ + \ 468 __extension_kinds_string + "\n", 469 ( 470 extension_kind_option_spec, 471 help_option_spec, 472 ) 473 ), 474 475 ("describe", 476 "Describe an extension.", 477 "EXTENSION-KIND NAME", 478 """Display details for the specified extension.""", 479 ( 480 attribute_option_spec, 481 list_long_option_spec, 482 help_option_spec, 483 ) 484 ), 485 486 ("help", 487 "Display usage summary.", 488 "", 489 "Display usage summary.", 490 () 491 ), 492 493 ("ls", 494 "List database contents.", 495 "[ NAME ... ]", 496 """ 497 List items stored in the database. 498 499 If no arguments are provided, the contents of the root 500 directory of the database are displayed. Otherwise, each of 501 the database is searched for each of the NAMEs. If the item 502 found is a directory then the contents of the directory are 503 displayed. 504 """, 505 ( 506 help_option_spec, 507 list_long_option_spec, 508 list_details_option_spec, 509 list_recursive_option_spec, 510 ), 511 ), 512 513 ("register", 514 "Register an extension class.", 515 "KIND CLASS", 516 """ 517 Register an extension class with QMTest. KIND is the kind of extension 518 class to register; it must be one of """ + __extension_kinds_string + """ 519 520 The CLASS gives the name of the class in the form 'module.class'. 521 522 QMTest will search the available extension class directories to find the 523 new CLASS. QMTest looks for files whose basename is the module name and 524 whose extension is either '.py', '.pyc', or '.pyo'. 525 526 QMTest will then attempt to load the extension class. If the extension 527 class cannot be loaded, QMTest will issue an error message to help you 528 debug the problem. Otherwise, QMTest will update the 'classes.qmc' file 529 in the directory containing the module to mention your new extension class. 530 """, 531 (help_option_spec,) 532 ), 533 534 ("remote", 535 "Run QMTest as a remote server.", 536 "", 537 """ 538 Runs QMTest as a remote server. This mode is only used by QMTest 539 itself when distributing tests across multiple machines. Users 540 should not directly invoke QMTest with this option. 541 """, 542 (help_option_spec,) 543 ), 544 545 ("report", 546 "Generate report from one or more test results.", 547 "[ result [-e expected] ]+", 548 """ 549 Generates a test report. The arguments are result files each optionally 550 followed by '-e' and an expectation file. This command attempts to reproduce 551 the test database structure, and thus requires the '--tdb' option. To generate 552 a flat test report specify the '--flat' option. 553 """, 554 (help_option_spec, 555 report_output_option_spec, 556 report_flat_option_spec) 557 ), 558 559 ("run", 560 "Run one or more tests.", 561 "[ ID ... ]", 562 """ 563 Runs tests. Optionally, generates a summary of the test run and a 564 record of complete test results. You may specify test IDs and test 565 suite IDs to run; omit arguments to run the entire test database. 566 567 Test results are written to "results.qmr". Use the '--output' option to 568 specify a different output file, or '--no-output' to supress results. 569 570 Use the '--format' option to specify the output format for the summary. 571 Valid formats are %s. 572 """ % _make_comma_separated_string(summary_formats, "and"), 573 ( 574 annotation_option_spec, 575 concurrent_option_spec, 576 context_file_spec, 577 context_option_spec, 578 format_option_spec, 579 help_option_spec, 580 no_output_option_spec, 581 outcomes_option_spec, 582 expectations_option_spec, 583 output_option_spec, 584 random_option_spec, 585 rerun_option_spec, 586 result_stream_spec, 587 seed_option_spec, 588 targets_option_spec, 589 ) 590 ), 591 592 ("summarize", 593 "Summarize results from a test run.", 594 "[FILE [ ID ... ]]", 595 """ 596 Loads a test results file and summarizes the results. FILE is the path 597 to the results file. Optionally, specify one or more test or suite IDs 598 whose results are shown. If none are specified, shows all tests that 599 did not pass. 600 601 Use the '--format' option to specify the output format for the summary. 602 Valid formats are %s. 603 """ % _make_comma_separated_string(summary_formats, "and"), 604 ( help_option_spec, 605 format_option_spec, 606 outcomes_option_spec, 607 expectations_option_spec, 608 output_option_spec, 609 result_stream_spec) 610 ), 611 612 ] 613 614 __version_output = \ 615 ("QMTest %s\n" 616 "Copyright (C) 2002 - 2007 CodeSourcery, Inc.\n" 617 "QMTest comes with ABSOLUTELY NO WARRANTY\n" 618 "For more information about QMTest visit http://www.qmtest.com\n") 619 """The string printed when the --version option is used. 620 621 There is one fill-in, for a string, which should contain the version 622 number.""" 623
624 - def __init__(self, argument_list, path):
625 """Construct a new QMTest. 626 627 Parses the argument list but does not execute the command. 628 629 'argument_list' -- The arguments to QMTest, not including the 630 initial argv[0]. 631 632 'path' -- The path to the QMTest executable.""" 633 634 global _the_qmtest 635 636 _the_qmtest = self 637 638 # Use the stadard stdout and stderr streams to emit messages. 639 self._stdout = sys.stdout 640 self._stderr = sys.stderr 641 642 # Build a trace object. 643 self.__tracer = Tracer() 644 645 # Build a command-line parser for this program. 646 self.__parser = qm.cmdline.CommandParser( 647 "qmtest", 648 self.global_options_spec, 649 self.commands_spec, 650 self.conflicting_option_specs) 651 # Parse the command line. 652 components = self.__parser.ParseCommandLine(argument_list) 653 # Unpack the results. 654 ( self.__global_options, 655 self.__command, 656 self.__command_options, 657 self.__arguments 658 ) = components 659 660 # If available, record the path to the qmtest executable. 661 self.__qmtest_path = path 662 663 # We have not yet computed the set of available targets. 664 self.targets = None 665 666 # The result stream class used for results files is the pickling 667 # version. 668 self.__file_result_stream_class_name \ 669 = "pickle_result_stream.PickleResultStream" 670 # The result stream class used for textual feed back. 671 self.__text_result_stream_class_name \ 672 = "text_result_stream.TextResultStream" 673 # The expected outcomes have not yet been loaded. 674 self.__expected_outcomes = None
675 676
677 - def __del__(self):
678 """Clean up global variables.""" 679 680 test.set_targets([])
681 682
683 - def HasGlobalOption(self, option):
684 """Return true if 'option' was specified as a global command. 685 686 'command' -- The long name of the option, but without the 687 preceding "--". 688 689 returns -- True if the option is present.""" 690 691 return option in map(lambda x: x[0], self.__global_options)
692 693
694 - def GetGlobalOption(self, option, default=None):
695 """Return the value of global 'option', or 'default' if omitted.""" 696 697 for opt, opt_arg in self.__global_options: 698 if opt == option: 699 return opt_arg 700 return default
701 702
703 - def HasCommandOption(self, option):
704 """Return true if command 'option' was specified.""" 705 706 for opt, opt_arg in self.__command_options: 707 if opt == option: 708 return 1 709 return 0
710 711
712 - def GetCommandOption(self, option, default = None):
713 """Return the value of command 'option'. 714 715 'option' -- The long form of an command-specific option. 716 717 'default' -- The default value to be returned if the 'option' 718 was not specified. This option should be the kind of an option 719 that takes an argument. 720 721 returns -- The value specified by the option, or 'default' if 722 the option was not specified.""" 723 724 for opt, opt_arg in self.__command_options: 725 if opt == option: 726 return opt_arg 727 return default
728 729
730 - def Execute(self):
731 """Execute the command. 732 733 returns -- 0 if the command was executed successfully. 1 if 734 there was a problem or if any tests run had unexpected outcomes.""" 735 736 # If --version was given, print the version number and exit. 737 # (The GNU coding standards require that the program take no 738 # further action after seeing --version.) 739 if self.HasGlobalOption("version"): 740 self._stdout.write(self.__version_output % qm.version) 741 return 0 742 # If the global help option was specified, display it and stop. 743 if (self.GetGlobalOption("help") is not None 744 or self.__command == "help"): 745 self._stdout.write(self.__parser.GetBasicHelp()) 746 return 0 747 # If the command help option was specified, display it and stop. 748 if self.GetCommandOption("help") is not None: 749 self.__WriteCommandHelp(self.__command) 750 return 0 751 752 # Make sure a command was specified. 753 if self.__command == "": 754 raise qm.cmdline.CommandError, qm.error("missing command") 755 756 # Look in several places to find the test database: 757 # 758 # 1. The command-line. 759 # 2. The QMTEST_DB_PATH environment variable. 760 # 3. The current directory. 761 db_path = self.GetGlobalOption("tdb") 762 if not db_path: 763 if os.environ.has_key(self.db_path_environment_variable): 764 db_path = os.environ[self.db_path_environment_variable] 765 else: 766 db_path = "." 767 # If the path is not already absolute, make it into an 768 # absolute path at this point. 769 if not os.path.isabs(db_path): 770 db_path = os.path.join(os.getcwd(), db_path) 771 # Normalize the path so that it is easy for the user to read 772 # if it is emitted in an error message. 773 self.__db_path = os.path.normpath(db_path) 774 database.set_path(self.__db_path) 775 776 error_occurred = 0 777 778 # Dispatch to the appropriate method. 779 if self.__command == "create-tdb": 780 return self.__ExecuteCreateTdb(db_path) 781 782 method = { 783 "create" : self.__ExecuteCreate, 784 "create-target" : self.__ExecuteCreateTarget, 785 "describe" : self.__ExecuteDescribe, 786 "extensions" : self.__ExecuteExtensions, 787 "gui" : self.__ExecuteServer, 788 "ls" : self.__ExecuteList, 789 "register" : self.__ExecuteRegister, 790 "remote" : self.__ExecuteRemote, 791 "run" : self.__ExecuteRun, 792 "report" : self.__ExecuteReport, 793 "summarize": self.__ExecuteSummarize, 794 }[self.__command] 795 796 return method()
797 798
799 - def GetDatabase(self):
800 """Return the test database to use. 801 802 returns -- The 'Database' to use for this execution. Raises an 803 exception if no 'Database' is available.""" 804 805 return database.get_database()
806 807
808 - def GetDatabaseIfAvailable(self):
809 """Return the test database to use. 810 811 returns -- The 'Database' to use for this execution, or 'None' 812 if no 'Database' is available.""" 813 814 try: 815 return self.GetDatabase() 816 except: 817 return None
818 819
820 - def GetTargetFileName(self):
821 """Return the path to the file containing target specifications. 822 823 returns -- The path to the file containing target specifications.""" 824 825 # See if the user requested a specific target file. 826 target_file_name = self.GetCommandOption("targets") 827 if target_file_name: 828 return target_file_name 829 # If there was no explicit option, use the "targets" file in the 830 # database directory. 831 return os.path.join(self.GetDatabase().GetConfigurationDirectory(), 832 self.target_file_name)
833 834
835 - def GetTargetsFromFile(self, file_name):
836 """Return the 'Target's specified in 'file_name'. 837 838 returns -- A list of the 'Target' objects specified in the 839 target specification file 'file_name'.""" 840 841 try: 842 document = qm.xmlutil.load_xml_file(file_name) 843 targets_element = document.documentElement 844 if targets_element.tagName != "targets": 845 raise QMException, \ 846 qm.error("could not load target file", 847 file = file_name) 848 targets = [] 849 for node in targets_element.getElementsByTagName("extension"): 850 # Parse the DOM node. 851 target_class, arguments \ 852 = (qm.extension.parse_dom_element 853 (node, 854 lambda n: get_extension_class(n, "target", 855 self.GetDatabase()))) 856 # Build the target. 857 target = target_class(self.GetDatabase(), arguments) 858 # Accumulate targets. 859 targets.append(target) 860 861 return targets 862 except Context: 863 raise QMException, \ 864 qm.error("could not load target file", 865 file=file_name)
866 867 868
869 - def GetTargets(self):
870 """Return the 'Target' objects specified by the user. 871 872 returns -- A sequence of 'Target' objects.""" 873 874 if not test.get_targets(): 875 file_name = self.GetTargetFileName() 876 if os.path.exists(file_name): 877 test.set_targets(self.GetTargetsFromFile(file_name)) 878 else: 879 # The target file does not exist. 880 concurrency = self.GetCommandOption("concurrency") 881 if concurrency is None: 882 # No concurrency specified. Run single-threaded. 883 concurrency = 1 884 else: 885 # Convert the concurrency to an integer. 886 try: 887 concurrency = int(concurrency) 888 except ValueError: 889 raise qm.cmdline.CommandError, \ 890 qm.error("concurrency not integer", 891 value=concurrency) 892 # Construct the target. 893 arguments = {} 894 arguments["name"] = "local" 895 arguments["group"] = "local" 896 if concurrency > 1: 897 class_name = "thread_target.ThreadTarget" 898 arguments["threads"] = concurrency 899 else: 900 class_name = "serial_target.SerialTarget" 901 target_class = get_extension_class(class_name, 902 'target', self.GetDatabase()) 903 test.set_targets([target_class(self.GetDatabase(), arguments)]) 904 905 return test.get_targets()
906 907
908 - def GetTracer(self):
909 """Return the 'Tracer' associated with this instance of QMTest. 910 911 returns -- The 'Tracer' associated with this instance of QMTest.""" 912 913 return self.__tracer
914 915
916 - def MakeContext(self):
917 """Construct a 'Context' object for running tests.""" 918 919 context = Context() 920 921 # First, see if a context file was specified on the command 922 # line. 923 use_implicit_context_file = 1 924 for option, argument in self.__command_options: 925 if option == "load-context": 926 use_implicit_context_file = 0 927 break 928 929 # If there is no context file, read the default context file. 930 if (use_implicit_context_file 931 and os.path.isfile(self.context_file_name)): 932 context.Read(self.context_file_name) 933 934 for option, argument in self.__command_options: 935 # Look for the '--load-context' option. 936 if option == "load-context": 937 context.Read(argument) 938 # Look for the '--context' option. 939 elif option == "context": 940 # Parse the argument. 941 name, value = qm.common.parse_assignment(argument) 942 943 try: 944 # Insert it into the context. 945 context[name] = value 946 except ValueError, msg: 947 # The format of the context key is invalid, but 948 # raise a 'CommandError' instead. 949 raise qm.cmdline.CommandError, msg 950 951 return context
952 953
954 - def GetExecutablePath(self):
955 """Return the path to the QMTest executable. 956 957 returns -- A string giving the path to the QMTest executable. 958 This is the path that should be used to invoke QMTest 959 recursively. Returns 'None' if the path to the QMTest 960 executable is uknown.""" 961 962 return self.__qmtest_path
963 964
965 - def GetFileResultStreamClass(self):
966 """Return the 'ResultStream' class used for results files. 967 968 returns -- The 'ResultStream' class used for results files.""" 969 970 return get_extension_class(self.__file_result_stream_class_name, 971 "result_stream", 972 self.GetDatabaseIfAvailable())
973
974 - def GetTextResultStreamClass(self):
975 """Return the 'ResultStream' class used for textual feedback. 976 977 returns -- the 'ResultStream' class used for textual 978 feedback.""" 979 980 return get_extension_class(self.__text_result_stream_class_name, 981 "result_stream", 982 self.GetDatabaseIfAvailable())
983 984
985 - def __GetAttributeOptions(self, expect_value = True):
986 """Return the attributes specified on the command line. 987 988 'expect_value' -- True if the attribute is to be parsed as 989 an assignment. 990 991 returns -- A dictionary. If expect_value is True, it 992 maps attribute names (strings) to values (strings). 993 Else it contains the raw attribute strings, mapping to None. 994 There is an entry for each attribute specified with 995 '--attribute' on the command line.""" 996 997 # There are no attributes yet. 998 attributes = {} 999 1000 # Go through the command line looking for attribute options. 1001 for option, argument in self.__command_options: 1002 if option == "attribute": 1003 if expect_value: 1004 name, value = qm.common.parse_assignment(argument) 1005 attributes[name] = value 1006 else: 1007 attributes[argument] = None 1008 return attributes
1009 1010
1011 - def __GetAnnotateOptions(self):
1012 """Return all annotate options. 1013 1014 returns -- A dictionary containing the annotation name / value pairs.""" 1015 1016 annotations = {} 1017 for option, argument in self.__command_options: 1018 if option == "annotate": 1019 name, value = qm.common.parse_assignment(argument) 1020 annotations[name] = value 1021 return annotations
1022 1023
1024 - def __ExecuteCreate(self):
1025 """Create a new extension file.""" 1026 1027 # Check that the right number of arguments are present. 1028 if len(self.__arguments) != 2: 1029 self.__WriteCommandHelp("create") 1030 return 2 1031 1032 # Figure out what database (if any) we are using. 1033 database = self.GetDatabaseIfAvailable() 1034 1035 # Get the extension kind. 1036 kind = self.__arguments[0] 1037 self.__CheckExtensionKind(kind) 1038 1039 extension_id = self.GetCommandOption("id") 1040 if extension_id is not None: 1041 if not database: 1042 raise QMException, qm.error("no db specified") 1043 if not database.IsModifiable(): 1044 raise QMException, qm.error("db not modifiable") 1045 extension_loader = database.GetExtension 1046 else: 1047 extension_loader = None 1048 1049 class_loader = lambda n: get_extension_class(n, kind, database) 1050 1051 # Process the descriptor. 1052 (extension_class, more_arguments) \ 1053 = (qm.extension.parse_descriptor 1054 (self.__arguments[1], class_loader, extension_loader)) 1055 1056 # Validate the --attribute options. 1057 arguments = self.__GetAttributeOptions() 1058 arguments = qm.extension.validate_arguments(extension_class, 1059 arguments) 1060 # Override the --attribute options with the arguments provided 1061 # as part of the descriptor. 1062 arguments.update(more_arguments) 1063 1064 if extension_id is not None: 1065 # Create the extension instance. Objects derived from 1066 # Runnable require magic additional arguments. 1067 if issubclass(extension_class, (Runnable, Suite)): 1068 extras = { extension_class.EXTRA_ID : extension_id, 1069 extension_class.EXTRA_DATABASE : database } 1070 else: 1071 extras = {} 1072 extension = extension_class(arguments, **extras) 1073 # Write the extension to the database. 1074 database.WriteExtension(extension_id, extension) 1075 else: 1076 # Figure out what file to use. 1077 filename = self.GetCommandOption("output") 1078 if filename is not None: 1079 file = open(filename, "w") 1080 else: 1081 file = sys.stdout 1082 # Write out the file. 1083 qm.extension.write_extension_file(extension_class, arguments, 1084 file) 1085 1086 return 0
1087 1088
1089 - def __ExecuteCreateTdb(self, db_path):
1090 """Handle the command for creating a new test database. 1091 1092 'db_path' -- The path at which to create the new test database.""" 1093 1094 if len(self.__arguments) != 0: 1095 self.__WriteCommandHelp("create-tdb") 1096 return 2 1097 1098 # Create the directory if it does not already exists. 1099 if not os.path.isdir(db_path): 1100 os.mkdir(db_path) 1101 # Create the configuration directory. 1102 config_dir = database.get_configuration_directory(db_path) 1103 if not os.path.isdir(config_dir): 1104 os.mkdir(config_dir) 1105 1106 # Reformulate this command in terms of "qmtest create". Start by 1107 # adding "--output <path>". 1108 self.__command_options.append(("output", 1109 database.get_configuration_file(db_path))) 1110 # Figure out what database class to use. 1111 class_name \ 1112 = self.GetCommandOption("class", "xml_database.XMLDatabase") 1113 # Add the extension kind and descriptor. 1114 self.__arguments.append("database") 1115 self.__arguments.append(class_name) 1116 # Now process this just like "qmtest create". 1117 self.__ExecuteCreate() 1118 # Print a helpful message. 1119 self._stdout.write(qm.message("new db message", path=db_path) + "\n") 1120 1121 return 0
1122 1123
1124 - def __ExecuteCreateTarget(self):
1125 """Create a new target file.""" 1126 1127 # Make sure that the arguments are correct. 1128 if (len(self.__arguments) < 2 or len(self.__arguments) > 3): 1129 self.__WriteCommandHelp("create-target") 1130 return 2 1131 1132 # Pull the required arguments out of the command line. 1133 target_name = self.__arguments[0] 1134 class_name = self.__arguments[1] 1135 if (len(self.__arguments) > 2): 1136 target_group = self.__arguments[2] 1137 else: 1138 target_group = "" 1139 1140 # Load the database. 1141 database = self.GetDatabase() 1142 1143 # Load the target class. 1144 target_class = get_extension_class(class_name, "target", database) 1145 1146 # Get the dictionary of class arguments. 1147 field_dictionary \ 1148 = qm.extension.get_class_arguments_as_dictionary(target_class) 1149 1150 # Get the name of the target file. 1151 file_name = self.GetTargetFileName() 1152 # If the file already exists, read it in. 1153 if os.path.exists(file_name): 1154 # Load the document. 1155 document = qm.xmlutil.load_xml_file(file_name) 1156 # If there is a previous entry for this target, discard it. 1157 targets_element = document.documentElement 1158 duplicates = [] 1159 for target_element \ 1160 in targets_element.getElementsByTagName("extension"): 1161 for attribute \ 1162 in target_element.getElementsByTagName("argument"): 1163 if attribute.getAttribute("name") == "name": 1164 name = field_dictionary["name"].\ 1165 GetValueFromDomNode(attribute.childNodes[0], 1166 None) 1167 if name == target_name: 1168 duplicates.append(target_element) 1169 break 1170 for duplicate in duplicates: 1171 targets_element.removeChild(duplicate) 1172 duplicate.unlink() 1173 else: 1174 document = (qm.xmlutil.create_dom_document 1175 (public_id = "QMTest/Target", 1176 document_element_tag = "targets")) 1177 targets_element = document.documentElement 1178 1179 # Get the attributes. 1180 attributes = self.__GetAttributeOptions() 1181 attributes["name"] = target_name 1182 attributes["group"] = target_group 1183 attributes = qm.extension.validate_arguments(target_class, 1184 attributes) 1185 1186 # Create the target element. 1187 target_element = qm.extension.make_dom_element(target_class, 1188 attributes, 1189 document) 1190 targets_element.appendChild(target_element) 1191 1192 # Write out the XML file. 1193 document.writexml(open(self.GetTargetFileName(), "w")) 1194 1195 return 0
1196 1197
1198 - def __ExecuteExtensions(self):
1199 """List the available extension classes.""" 1200 1201 # Check that the right number of arguments are present. 1202 if len(self.__arguments) != 0: 1203 self.__WriteCommandHelp("extensions") 1204 return 2 1205 1206 database = self.GetDatabaseIfAvailable() 1207 1208 # Figure out what kinds of extensions we're going to list. 1209 kind = self.GetCommandOption("kind") 1210 if kind: 1211 self.__CheckExtensionKind(kind) 1212 kinds = [kind] 1213 else: 1214 kinds = base.extension_kinds 1215 1216 for kind in kinds: 1217 # Get the available classes. 1218 names = qm.test.base.get_extension_class_names(kind, 1219 database, 1220 self.__db_path) 1221 # Build structured text describing the classes. 1222 description = "** Available %s classes **\n\n" % kind 1223 for n in names: 1224 description += " * " + n + "\n\n " 1225 # Try to load the class to get more information. 1226 try: 1227 extension_class = get_extension_class(n, kind, database) 1228 description \ 1229 += qm.extension.get_class_description(extension_class, 1230 brief=1) 1231 except: 1232 description += ("No description available: " 1233 "could not load class.") 1234 description += "\n\n" 1235 1236 self._stdout.write(qm.structured_text.to_text(description)) 1237 1238 return 0
1239 1240
1241 - def __ExecuteDescribe(self):
1242 """Describe an extension.""" 1243 1244 # Check that the right number of arguments are present. 1245 if len(self.__arguments) != 2: 1246 self.__WriteCommandHelp("describe") 1247 return 2 1248 1249 kind = self.__arguments[0] 1250 long_format = self.GetCommandOption("long") != None 1251 1252 database = self.GetDatabaseIfAvailable() 1253 class_ = get_extension_class(self.__arguments[1], kind, database) 1254 1255 attributes = (self.__GetAttributeOptions(False) 1256 or class_._argument_dictionary) 1257 1258 print "" 1259 print "class name:", get_extension_class_name(class_) 1260 print " ", get_class_description(class_, brief=not long_format) 1261 print "" 1262 print "class attributes:" 1263 tab = max([len(name) for name in attributes]) 1264 for name in attributes: 1265 field = class_._argument_dictionary.get(name) 1266 if not field: 1267 self._stderr.write("Unknown attribute '%s'.\n"%name) 1268 return 2 1269 value = field.GetDefaultValue() 1270 description = field.GetDescription() 1271 if not long_format: 1272 description = qm.structured_text.get_first(description) 1273 print " %-*s %s"%(tab, name, description)
1274 1275
1276 - def __ExecuteList(self):
1277 """List the contents of the database.""" 1278 1279 database = self.GetDatabase() 1280 1281 long_format = self.HasCommandOption("long") 1282 details_format = self.HasCommandOption("details") 1283 recursive = self.HasCommandOption("recursive") 1284 1285 # If no arguments are specified, list the root directory. 1286 args = self.__arguments or ("",) 1287 1288 # Get all the extensions to list. 1289 extensions = {} 1290 for arg in args: 1291 extension = database.GetExtension(arg) 1292 if not extension: 1293 raise QMException, qm.error("no such ID", id = arg) 1294 if isinstance(extension, qm.test.suite.Suite): 1295 if recursive: 1296 test_ids, suite_ids = extension.GetAllTestAndSuiteIds() 1297 extensions.update([(i, database.GetExtension(i)) 1298 for i in test_ids + suite_ids]) 1299 else: 1300 ids = extension.GetTestIds() + extension.GetSuiteIds() 1301 extensions.update([(i, database.GetExtension(i)) 1302 for i in ids]) 1303 else: 1304 extensions[arg] = extension 1305 1306 # Get the labels for the extensions, in alphabetical order. 1307 ids = extensions.keys() 1308 ids.sort() 1309 1310 # In the short format, just print the labels. 1311 if not long_format: 1312 for id in ids: 1313 print >> sys.stdout, id 1314 return 0 1315 1316 # In the long format, print three columns: the extension kind, 1317 # class name, and the label. We make two passes over the 1318 # extensions so that the output will be tidy. In the first pass, 1319 # calculate the width required for the first two columns in the 1320 # output. The actual output occurs in the second pass. 1321 longest_kind = 0 1322 longest_class = 0 1323 for i in (0, 1): 1324 for id in ids: 1325 extension = extensions[id] 1326 if isinstance(extension, 1327 qm.test.directory_suite.DirectorySuite): 1328 kind = "directory" 1329 class_name = "" 1330 else: 1331 kind = extension.__class__.kind 1332 class_name = extension.GetClassName() 1333 1334 if i == 0: 1335 kind_len = len(kind) + 1 1336 if kind_len > longest_kind: 1337 longest_kind = kind_len 1338 class_len = len(class_name) + 1 1339 if class_len > longest_class: 1340 longest_class = class_len 1341 else: 1342 print >> sys.stdout, \ 1343 "%-*s%-*s%s" % (longest_kind, kind, 1344 longest_class, class_name, id) 1345 if details_format: 1346 tab = max([len(name) 1347 for name in extension._argument_dictionary]) 1348 for name in extension._argument_dictionary: 1349 value = str(getattr(extension, name)) 1350 print " %-*s %s"%(tab, name, value) 1351 1352 return 0
1353 1354
1355 - def __ExecuteRegister(self):
1356 """Register a new extension class.""" 1357 1358 # Make sure that the KIND and CLASS were specified. 1359 if (len(self.__arguments) != 2): 1360 self.__WriteCommandHelp("register") 1361 return 2 1362 kind = self.__arguments[0] 1363 class_name = self.__arguments[1] 1364 1365 # Check that the KIND is valid. 1366 self.__CheckExtensionKind(kind) 1367 1368 # Check that the CLASS_NAME is well-formed. 1369 if class_name.count('.') != 1: 1370 raise qm.cmdline.CommandError, \ 1371 qm.error("invalid class name", 1372 class_name = class_name) 1373 module, name = class_name.split('.') 1374 1375 # Try to load the database. It may provide additional 1376 # directories to search. 1377 database = self.GetDatabaseIfAvailable() 1378 # Hunt through all of the extension class directories looking 1379 # for an appropriately named module. 1380 found = None 1381 directories = get_extension_directories(kind, database, 1382 self.__db_path) 1383 for directory in directories: 1384 for ext in (".py", ".pyc", ".pyo"): 1385 file_name = os.path.join(directory, module + ext) 1386 if os.path.exists(file_name): 1387 found = file_name 1388 break 1389 if found: 1390 break 1391 1392 # If we could not find the module, issue an error message. 1393 if not found: 1394 raise qm.QMException, \ 1395 qm.error("module does not exist", 1396 module = module) 1397 1398 # Inform the user of the location in which QMTest found the 1399 # module. (Sometimes, there might be another module with the 1400 # same name in the path. Telling the user where we've found 1401 # the module will help the user to deal with this situation.) 1402 self._stdout.write(qm.structured_text.to_text 1403 (qm.message("loading class", 1404 class_name = name, 1405 file_name = found))) 1406 1407 # We have found the module. Try loading it. 1408 extension_class = get_extension_class_from_directory(class_name, 1409 kind, 1410 directory, 1411 directories) 1412 1413 # Create or update the classes.qmc file. 1414 classes_file_name = os.path.join(directory, "classes.qmc") 1415 1416 # Create a new DOM document for the class directory. 1417 document = (qm.xmlutil.create_dom_document 1418 (public_id = "Class-Directory", 1419 document_element_tag="class-directory")) 1420 1421 # Copy entries from the old file to the new one. 1422 extensions = get_extension_class_names_in_directory(directory) 1423 for k, ns in extensions.iteritems(): 1424 for n in ns: 1425 # Remove previous entries for the class being added. 1426 if k == kind and n == class_name: 1427 continue 1428 element = document.createElement("class") 1429 element.setAttribute("kind", k) 1430 element.setAttribute("name", n) 1431 document.documentElement.appendChild(element) 1432 1433 # Add an entry for the new element. 1434 element = document.createElement("class") 1435 element.setAttribute("kind", kind) 1436 element.setAttribute("name", class_name) 1437 document.documentElement.appendChild(element) 1438 1439 # Write out the file. 1440 document.writexml(open(classes_file_name, "w"), 1441 addindent = " ", newl = "\n") 1442 1443 return 0
1444 1445
1446 - def __ExecuteSummarize(self):
1447 """Read in test run results and summarize.""" 1448 1449 # If no results file is specified, use a default value. 1450 if len(self.__arguments) == 0: 1451 results_path = self.results_file_name 1452 else: 1453 results_path = self.__arguments[0] 1454 1455 database = self.GetDatabaseIfAvailable() 1456 1457 # The remaining arguments, if any, are test and suite IDs. 1458 id_arguments = self.__arguments[1:] 1459 # Are there any? 1460 # '.' is an alias for <all>, and thus shadows other selectors. 1461 if len(id_arguments) > 0 and not '.' in id_arguments: 1462 ids = set() 1463 # Expand arguments into test/resource IDs. 1464 if database: 1465 for id in id_arguments: 1466 extension = database.GetExtension(id) 1467 if not extension: 1468 raise qm.cmdline.CommandError, \ 1469 qm.error("no such ID", id = id) 1470 if extension.kind == database.SUITE: 1471 ids.update(extension.GetAllTestAndSuiteIds()[0]) 1472 else: 1473 ids.add(id) 1474 else: 1475 ids = set(id_arguments) 1476 else: 1477 # No IDs specified. Show all test and resource results. 1478 # Don't show any results by test suite though. 1479 ids = None 1480 1481 # Get an iterator over the results. 1482 try: 1483 results = base.load_results(results_path, database) 1484 except Exception, exception: 1485 raise QMException, \ 1486 qm.error("invalid results file", 1487 path=results_path, 1488 problem=str(exception)) 1489 1490 any_unexpected_outcomes = 0 1491 1492 # Load expectations. 1493 expectations = (self.GetCommandOption('expectations') or 1494 self.GetCommandOption('outcomes')) 1495 expectations = base.load_expectations(expectations, 1496 database, 1497 results.GetAnnotations()) 1498 # Compute the list of result streams to which output should be 1499 # written. 1500 streams = self.__CreateResultStreams(self.GetCommandOption("output"), 1501 results.GetAnnotations(), 1502 expectations) 1503 1504 resource_results = {} 1505 for r in results: 1506 if r.GetKind() != Result.TEST: 1507 if ids is None or r.GetId() in ids: 1508 for s in streams: 1509 s.WriteResult(r) 1510 elif r.GetKind() == Result.RESOURCE_SETUP: 1511 resource_results[r.GetId()] = r 1512 continue 1513 # We now known that r is test result. If it's not one 1514 # that interests us, we're done. 1515 if ids is not None and r.GetId() not in ids: 1516 continue 1517 # If we're filtering, and this test was not run because it 1518 # depended on a resource that was not set up, emit the 1519 # resource result here. 1520 if (ids is not None 1521 and r.GetOutcome() == Result.UNTESTED 1522 and r.has_key(Result.RESOURCE)): 1523 rid = r[Result.RESOURCE] 1524 rres = resource_results.get(rid) 1525 if rres: 1526 del resource_results[rid] 1527 for s in streams: 1528 s.WriteResult(rres) 1529 # Write out the test result. 1530 for s in streams: 1531 s.WriteResult(r) 1532 if (not any_unexpected_outcomes 1533 and r.GetOutcome() != expectations.Lookup(r.GetId())): 1534 any_unexpected_outcomes = 1 1535 # Shut down the streams. 1536 for s in streams: 1537 s.Summarize() 1538 1539 return any_unexpected_outcomes
1540 1541
1542 - def __ExecuteRemote(self):
1543 """Execute the 'remote' command.""" 1544 1545 database = self.GetDatabase() 1546 1547 # Get the target class. For now, we always run in serial when 1548 # running remotely. 1549 target_class = get_extension_class("serial_target.SerialTarget", 1550 'target', database) 1551 # Build the target. 1552 target = target_class(database, { "name" : "child" }) 1553 1554 # Start the target. 1555 response_queue = Queue.Queue(0) 1556 target.Start(response_queue) 1557 1558 # Read commands from standard input, and reply to standard 1559 # output. 1560 while 1: 1561 # Read the command. 1562 command = cPickle.load(sys.stdin) 1563 1564 # If the command is just a string, it should be 1565 # the 'Stop' command. 1566 if isinstance(command, types.StringType): 1567 assert command == "Stop" 1568 target.Stop() 1569 break 1570 1571 # Decompose command. 1572 method, id, context = command 1573 # Get the descriptor. 1574 descriptor = database.GetTest(id) 1575 # Run it. 1576 target.RunTest(descriptor, context) 1577 # There are no results yet. 1578 results = [] 1579 # Read all of the results. 1580 while 1: 1581 try: 1582 result = response_queue.get(0) 1583 results.append(result) 1584 except Queue.Empty: 1585 # There are no more results. 1586 break 1587 # Pass the results back. 1588 cPickle.dump(results, sys.stdout) 1589 # The standard output stream is bufferred, but the master 1590 # will block waiting for a response, so we must flush 1591 # the buffer here. 1592 sys.stdout.flush() 1593 1594 return 0
1595 1596
1597 - def __ExecuteReport(self):
1598 """Execute a 'report' command.""" 1599 1600 output = self.GetCommandOption("output") 1601 flat = self.GetCommandOption("flat") != None 1602 1603 # Check that at least one result file is present. 1604 if not output or len(self.__arguments) < 1: 1605 self.__WriteCommandHelp("report") 1606 return 2 1607 1608 # If the database can be loaded, use it to find all 1609 # available tests. The default (non-flat) format requires a database. 1610 if flat: 1611 database = self.GetDatabaseIfAvailable() 1612 else: 1613 database = self.GetDatabase() 1614 1615 report_generator = ReportGenerator(output, database) 1616 report_generator.GenerateReport(flat, self.__arguments)
1617 1618
1619 - def __ExecuteRun(self):
1620 """Execute a 'run' command.""" 1621 1622 database = self.GetDatabase() 1623 1624 # Handle the 'seed' option. First create the random number 1625 # generator we will use. 1626 seed = self.GetCommandOption("seed") 1627 if seed: 1628 # A seed was specified. It should be an integer. 1629 try: 1630 seed = int(seed) 1631 except ValueError: 1632 raise qm.cmdline.CommandError, \ 1633 qm.error("seed not integer", seed=seed) 1634 # Use the specified seed. 1635 random.seed(seed) 1636 1637 # Figure out what tests to run. 1638 if len(self.__arguments) == 0: 1639 # No IDs specified; run the entire test database. 1640 self.__arguments.append("") 1641 elif '.' in self.__arguments: 1642 # '.' is an alias for <all>, and thus shadows other selectors. 1643 self.__arguments = [""] 1644 1645 # Expand arguments in test IDs. 1646 try: 1647 test_ids, test_suites \ 1648 = self.GetDatabase().ExpandIds(self.__arguments) 1649 except (qm.test.database.NoSuchTestError, 1650 qm.test.database.NoSuchSuiteError), exception: 1651 raise qm.cmdline.CommandError, str(exception) 1652 except ValueError, exception: 1653 raise qm.cmdline.CommandError, \ 1654 qm.error("no such ID", id=str(exception)) 1655 1656 # Handle the --annotate options. 1657 annotations = self.__GetAnnotateOptions() 1658 1659 # Load expectations. 1660 expectations = (self.GetCommandOption('expectations') or 1661 self.GetCommandOption('outcomes')) 1662 expectations = base.load_expectations(expectations, 1663 database, 1664 annotations) 1665 # Filter the set of tests to be run, eliminating any that should 1666 # be skipped. 1667 test_ids = self.__FilterTestsToRun(test_ids, expectations) 1668 1669 # Figure out which targets to use. 1670 targets = self.GetTargets() 1671 # Compute the context in which the tests will be run. 1672 context = self.MakeContext() 1673 1674 # Handle the --output option. 1675 if self.HasCommandOption("no-output"): 1676 # User specified no output. 1677 result_file_name = None 1678 else: 1679 result_file_name = self.GetCommandOption("output") 1680 if result_file_name is None: 1681 # By default, write results to a default file. 1682 result_file_name = self.results_file_name 1683 1684 # Compute the list of result streams to which output should be 1685 # written. 1686 result_streams = self.__CreateResultStreams(result_file_name, 1687 annotations, 1688 expectations) 1689 1690 if self.HasCommandOption("random"): 1691 # Randomize the order of the tests. 1692 random.shuffle(test_ids) 1693 else: 1694 test_ids.sort() 1695 1696 # Run the tests. 1697 engine = ExecutionEngine(database, test_ids, context, targets, 1698 result_streams, 1699 expectations) 1700 if engine.Run(): 1701 return 1 1702 1703 return 0
1704 1705
1706 - def __ExecuteServer(self):
1707 """Process the server command.""" 1708 1709 database = self.GetDatabase() 1710 1711 # Get the port number specified by a command option, if any. 1712 # Otherwise use a default value. 1713 port_number = self.GetCommandOption("port", default=0) 1714 try: 1715 port_number = int(port_number) 1716 except ValueError: 1717 raise qm.cmdline.CommandError, qm.error("bad port number") 1718 # Get the local address specified by a command option, if any. 1719 # If not was specified, use the loopback address. The loopback 1720 # address is used by default for security reasons; it restricts 1721 # access to the QMTest server to users on the local machine. 1722 address = self.GetCommandOption("address", default="127.0.0.1") 1723 1724 # If a log file was requested, open it now. 1725 log_file_path = self.GetCommandOption("log-file") 1726 if log_file_path == "-": 1727 # A hyphen path name means standard output. 1728 log_file = sys.stdout 1729 elif log_file_path is None: 1730 # No log file. 1731 log_file = None 1732 else: 1733 # Otherwise, it's a file name. Open it for append. 1734 log_file = open(log_file_path, "a+") 1735 1736 # If a PID file was requested, create it now. 1737 pid_file_path = self.GetCommandOption("pid-file") 1738 if pid_file_path is not None: 1739 # If a PID file was requested, but no explicit path was 1740 # given, use a default value. 1741 if not pid_file_path: 1742 pid_file_path = qm.common.rc.Get("pid-file", 1743 "/var/run/qmtest.pid", 1744 "qmtest") 1745 try: 1746 pid_file = open(pid_file_path, "w") 1747 except IOError, e: 1748 raise qm.cmdline.CommandError, str(e) 1749 else: 1750 pid_file = None 1751 1752 # Create a run database, if requested. 1753 run_db = None 1754 directory = self.GetCommandOption("results", default="") 1755 if directory: 1756 directory = os.path.normpath(directory) 1757 run_db = DirRunDatabase(directory, database) 1758 1759 # Load expectations. Only support the 'outcome' option here, 1760 # as 'expectations' in general are unsupported with this GUI. 1761 expectations = self.GetCommandOption('outcomes') 1762 expectations = base.load_expectations(expectations, database) 1763 # Make sure this is either an ExpectationDatabase or a 1764 # PreviousRun 1765 if not type(expectations) in (ExpectationDatabase, PreviousTestRun): 1766 raise qm.cmdline.CommandError, 'not a valid results file' 1767 # Figure out which targets to use. 1768 targets = self.GetTargets() 1769 # Compute the context in which the tests will be run. 1770 context = self.MakeContext() 1771 # Set up the server. 1772 server = QMTestServer(database, 1773 port_number, address, 1774 log_file, targets, context, 1775 expectations, 1776 run_db) 1777 port_number = server.GetServerAddress()[1] 1778 1779 # Construct the URL to the main page on the server. 1780 if address == "": 1781 url_address = qm.platform.get_host_name() 1782 else: 1783 url_address = address 1784 if run_db: 1785 url = "http://%s:%d/report/dir" % (url_address, port_number) 1786 else: 1787 url = "http://%s:%d/test/dir" % (url_address, port_number) 1788 1789 if not self.HasCommandOption("no-browser"): 1790 # Now that the server is bound to its address, start the 1791 # web browser. 1792 qm.platform.open_in_browser(url) 1793 1794 message = qm.message("server url", url=url) 1795 sys.stderr.write(message + "\n") 1796 1797 # Become a daemon, if appropriate. 1798 if self.GetCommandOption("daemon") is not None: 1799 # Fork twice. 1800 if os.fork() != 0: 1801 os._exit(0) 1802 if os.fork() != 0: 1803 os._exit(0) 1804 # This process is now the grandchild of the original 1805 # process. 1806 1807 # Write out the PID file. The correct PID is not known until 1808 # after the transformation to a daemon has taken place. 1809 try: 1810 if pid_file: 1811 pid_file.write(str(os.getpid())) 1812 pid_file.close() 1813 1814 # Accept requests. 1815 try: 1816 server.Run() 1817 except qm.platform.SignalException, se: 1818 if se.GetSignalNumber() == signal.SIGTERM: 1819 # If we receive SIGTERM, shut down. 1820 pass 1821 else: 1822 # Other signals propagate outwards. 1823 raise 1824 except KeyboardInterrupt: 1825 # If we receive a keyboard interrupt (Ctrl-C), shut down. 1826 pass 1827 finally: 1828 if pid_file: 1829 os.remove(pid_file_path) 1830 1831 return 0
1832 1833
1834 - def __WriteCommandHelp(self, command):
1835 """Write out help information about 'command'. 1836 1837 'command' -- The name of the command for which help information 1838 is required.""" 1839 1840 self._stderr.write(self.__parser.GetCommandHelp(command))
1841
1842 - def __FilterTestsToRun(self, test_ids, expectations):
1843 """Return those tests from 'test_ids' that should be run. 1844 1845 'test_ids' -- A sequence of test ids. 1846 1847 'expectations' -- An ExpectationDatabase. 1848 1849 returns -- Those elements of 'test_names' that are not to be 1850 skipped. If 'a' precedes 'b' in 'test_ids', and both 'a' and 1851 'b' are present in the result, 'a' will precede 'b' in the 1852 result.""" 1853 1854 # The --rerun option indicates that only failing tests should 1855 # be rerun. 1856 rerun_file_name = self.GetCommandOption("rerun") 1857 if rerun_file_name: 1858 # Load the outcomes from the file specified. 1859 outcomes = base.load_outcomes(rerun_file_name, 1860 self.GetDatabase()) 1861 # Filter out tests that have unexpected outcomes. 1862 test_ids = [t for t in test_ids 1863 if outcomes.get(t, Result.PASS) 1864 != expectations.Lookup(t).GetOutcome()] 1865 1866 return test_ids
1867 1868
1869 - def __CheckExtensionKind(self, kind):
1870 """Check that 'kind' is a valid extension kind. 1871 1872 'kind' -- A string giving the name of an extension kind. If the 1873 'kind' does not name a valid extension kind, an appropriate 1874 exception is raised.""" 1875 1876 if kind not in base.extension_kinds: 1877 raise qm.cmdline.CommandError, \ 1878 qm.error("invalid extension kind", 1879 kind = kind)
1880 1881
1882 - def __CreateResultStreams(self, output_file, annotations, expectations):
1883 """Return the result streams to use. 1884 1885 'output_file' -- If not 'None', the name of a file to which 1886 the standard results file format should be written. 1887 1888 'annotations' -- A dictionary with annotations for this test run. 1889 1890 'expectations' -- An ExpectationDatabase. 1891 1892 returns -- A list of 'ResultStream' objects, as indicated by the 1893 user.""" 1894 1895 database = self.GetDatabaseIfAvailable() 1896 1897 result_streams = [] 1898 1899 arguments = {} 1900 arguments['expected_outcomes'] = expectations.GetExpectedOutcomes() 1901 1902 # Look up the summary format. 1903 format = self.GetCommandOption("format", "") 1904 if format and format not in self.summary_formats: 1905 # Invalid format. Complain. 1906 valid_format_string = string.join( 1907 map(lambda f: '"%s"' % f, self.summary_formats), ", ") 1908 raise qm.cmdline.CommandError, \ 1909 qm.error("invalid results format", 1910 format=format, 1911 valid_formats=valid_format_string) 1912 if format != "none": 1913 args = { "format" : format } 1914 args.update(arguments) 1915 stream = self.GetTextResultStreamClass()(args) 1916 result_streams.append(stream) 1917 1918 f = lambda n: get_extension_class(n, "result_stream", database) 1919 1920 # Look for all of the "--result-stream" options. 1921 for opt, opt_arg in self.__command_options: 1922 if opt == "result-stream": 1923 ec, args = qm.extension.parse_descriptor(opt_arg, f) 1924 args.update(arguments) 1925 result_streams.append(ec(args)) 1926 1927 # If there is an output file, create a standard results file on 1928 # that file. 1929 if output_file is not None: 1930 rs = (self.GetFileResultStreamClass() 1931 ({ "filename" : output_file})) 1932 result_streams.append(rs) 1933 1934 for name, value in annotations.iteritems(): 1935 for rs in result_streams: 1936 rs.WriteAnnotation(name, value) 1937 1938 return result_streams
1939 1940 ######################################################################## 1941 # Functions 1942 ######################################################################## 1943
1944 -def get_qmtest():
1945 """Returns the global QMTest object. 1946 1947 returns -- The 'QMTest' object that corresponds to the currently 1948 executing thread. 1949 1950 At present, there is only one QMTest object per process. In the 1951 future, however, there may be more than one. Then, this function 1952 will return different values in different threads.""" 1953 1954 return _the_qmtest
1955 1956 ######################################################################## 1957 # Local Variables: 1958 # mode: python 1959 # indent-tabs-mode: nil 1960 # fill-column: 72 1961 # End: 1962

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.result_stream-module.html0000664000076400007640000000213511122067144027212 0ustar stefanstefan result_stream

Module result_stream


Classes

ResultStream

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python_label-module.html0000664000076400007640000001131511122067145027653 0ustar stefanstefan qm.test.classes.python_label
Package qm :: Package test :: Package classes :: Module python_label
[hide private]
[frames] | no frames]

Module python_label

source code

Classes [hide private]
  PythonLabel
A 'PythonLabel' is a 'Label' that uses the 'a.b.c' naming scheme.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command.ExecTestBase-class.html0000664000076400007640000005506111122067146030756 0ustar stefanstefan qm.test.classes.command.ExecTestBase
Package qm :: Package test :: Package classes :: Module command :: Class ExecTestBase
[hide private]
[frames] | no frames]

Class ExecTestBase

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
                  test.Test --+
                              |
                             ExecTestBase

Check a program's output and exit code.

An 'ExecTestBase' runs a program and compares its standard output, standard error, and exit code with expected values. The program may be provided with command-line arguments and/or standard input.

The test passes if the standard output, standard error, and exit code are identical to the expected values.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
MakeEnvironment(self, context)
Construct the environment for executing the target program.
source code
 
ValidateOutput(self, stdout, stderr, result)
Validate the output of the program.
source code
 
RunProgram(self, program, arguments, context, result)
Run the 'program'.
source code
 
__CompareText(self, s1, s2)
Compare 's1' and 's2', ignoring line endings.
source code

Inherited from test.Test: GetTargetGroup, Run

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "stdin", title= "Standa...
A list of the arguments to the extension class.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

ValidateOutput(self, stdout, stderr, result)

source code 

Validate the output of the program.

'stdout' -- A string containing the data written to the standard output stream.

'stderr' -- A string containing the data written to the standard error stream.

'result' -- A 'Result' object. It may be used to annotate the outcome according to the content of stderr.

returns -- A list of strings giving causes of failure.

RunProgram(self, program, arguments, context, result)

source code 

Run the 'program'.

'program' -- The path to the program to run.

'arguments' -- A list of the arguments to the program. This list must contain a first argument corresponding to 'argv[0]'.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

__CompareText(self, s1, s2)

source code 

Compare 's1' and 's2', ignoring line endings.

's1' -- A string.

's2' -- A string.

returns -- True if 's1' and 's2' are the same, ignoring differences in line endings.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "stdin", title= "Standard Input", verbatim=\
 "true", multiline= "true", description= """The contents of the standa\
rd input stream.

            If this field is left blank, the standard input stream wil\
l
            contain no data."""), qm.fields.SetField(qm.fields.TextFie\
ld(name= "environment", title= "Environment", description= """Addition\
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.TestResultsPage-class.html0000664000076400007640000007205711122067151030014 0ustar stefanstefan qm.test.web.web.TestResultsPage
Package qm :: Package test :: Package web :: Module web :: Class TestResultsPage
[hide private]
[frames] | no frames]

Class TestResultsPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      TestResultsPage

DTML page for displaying test results.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server)
Construct a new 'TestResultsPage'.
source code
 
GetOutcomes(self)
Return the list of result outcomes.
source code
 
GetTotal(self)
Return the total number of tests.
source code
 
GetTotalUnexpected(self)
Return the total number of unexpected results.
source code
 
GetResultsWithOutcome(self, outcome)
Return the number of tests with the given 'outcome'.
source code
 
GetCount(self, outcome)
Return the number of tests with the given 'outcome'.
source code
 
GetUnexpectedCount(self, outcome)
Return the number of tests with the given 'outcome'.
source code
 
GetRelativeResults(self, results, expected)
Return the results that match, or fail to match, expectations.
source code
 
GetDetailUrl(self, test_id)
Return the detail URL for a test.
source code
 
IsFinished(self)
Return true iff no more results are forthcoming.
source code
 
GetRefreshDelay(self)
Returns the number of seconds to wait before refreshing the page.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server)
(Constructor)

source code 

Construct a new 'TestResultsPage'.

'server' -- The 'QMTestServer' creating this page.

Overrides: web.DtmlPage.__init__

GetOutcomes(self)

source code 

Return the list of result outcomes.

returns -- A sequence of result outcomes.

GetTotal(self)

source code 

Return the total number of tests.

returns -- The total number of tests.

GetTotalUnexpected(self)

source code 

Return the total number of unexpected results.

returns -- The total number of unexpected results.

GetResultsWithOutcome(self, outcome)

source code 

Return the number of tests with the given 'outcome'.

'outcome' -- One of the 'Result.outcomes'.

returns -- The results with the given 'outcome'.

GetCount(self, outcome)

source code 

Return the number of tests with the given 'outcome'.

'outcome' -- One of the 'Result.outcomes'.

returns -- The number of tests with the given 'outcome'.

GetUnexpectedCount(self, outcome)

source code 

Return the number of tests with the given 'outcome'.

'outcome' -- One of the 'Result.outcomes'.

returns -- The number of tests with the given 'outcome' that were expected to have some other outcome.

GetRelativeResults(self, results, expected)

source code 

Return the results that match, or fail to match, expectations.

'results' -- A sequence of 'Result' objects.

'expected' -- A boolean. If true, expected results are returned. If false, unexpected results are returned.

GetDetailUrl(self, test_id)

source code 

Return the detail URL for a test.

'test_id' -- The name of the test.

returns -- The URL that contains details about the 'test_id'.

IsFinished(self)

source code 

Return true iff no more results are forthcoming.

returns -- True if no more tests are running.

Overrides: QMTestPage.IsFinished

GetRefreshDelay(self)

source code 

Returns the number of seconds to wait before refreshing the page.

returns -- The number of seconds to wait before refreshing this page. A value of zero means that te page should never be refreshed. This function is only called if 'IsFinished' returns true.

Overrides: QMTestPage.GetRefreshDelay

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.NoSessionError-class.html0000664000076400007640000001533311122067151026110 0ustar stefanstefan qm.web.NoSessionError
Package qm :: Module web :: Class NoSessionError
[hide private]
[frames] | no frames]

Class NoSessionError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  NoSessionError

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/string-module.html0000664000076400007640000017041411122067145023461 0ustar stefanstefan string
Module string
[hide private]
[frames] | no frames]

Module string

source code

A collection of string operations (most are no longer used).

Warning: most of the code you see here isn't normally used nowadays. Beginning with Python 1.6, many of these functions are implemented as methods on the standard string object. They used to be implemented by a built-in module called strop, but strop is now obsolete itself.

Public module variables:

whitespace -- a string containing all characters considered whitespace lowercase -- a string containing all characters considered lowercase letters uppercase -- a string containing all characters considered uppercase letters letters -- a string containing all characters considered letters digits -- a string containing all characters considered decimal digits hexdigits -- a string containing all characters considered hexadecimal digits octdigits -- a string containing all characters considered octal digits punctuation -- a string containing all characters considered punctuation printable -- a string containing all characters considered printable

Classes [hide private]
  Template
A string class for supporting $-substitutions.
  _TemplateMetaclass
  _multimap
Helper class for combining multiple mappings.
Functions [hide private]
float
atof(s)
Return the floating point number represented by the string s.
source code
int
atoi(s, base=...)
Return the integer represented by the string s in the given base, which defaults to 10.
source code
long
atol(s, base=...)
Return the long integer represented by the string s in the given base, which defaults to 10.
source code
string
capitalize(s)
Return a copy of the string s with only its first character capitalized.
source code
 
capwords(s, sep=None)
capwords(s, [sep]) -> string
source code
string
center(s, width, fillchar=...)
Return a center version of s, in a field of the specified width.
source code
int
count(s, sub, start=..., end=...)
Return the number of occurrences of substring sub in string s[start:end].
source code
string
expandtabs(s, tabsize=...)
Return a copy of the string s with all tab characters replaced by the appropriate number of spaces, depending on the current column, and the tabsize (default 8).
source code
in
find(s, sub, start=... , end=...)
Return the lowest index in s where substring sub is found, such that sub is contained within s[start,end].
source code
int
index(s, sub, start=... , end=...)
Like find but raises ValueError when the substring is not found.
source code
string
join(list, sep=...)
Return a string composed of the words in list, with intervening occurrences of sep.
source code
string
joinfields(list, sep=...)
Return a string composed of the words in list, with intervening occurrences of sep.
source code
string
ljust(s, width, fillchar=...)
Return a left-justified version of s, in a field of the specified width, padded with spaces as needed.
source code
string
lower(s)
Return a copy of the string s converted to lowercase.
source code
string
lstrip(s, chars=...)
Return a copy of the string s with leading whitespace removed.
source code
 
replace(s, old, new, maxsplit=-1)
replace (str, old, new[, maxsplit]) -> string
source code
int
rfind(s, sub, start=... , end=...)
Return the highest index in s where substring sub is found, such that sub is contained within s[start,end].
source code
int
rindex(s, sub, start=... , end=...)
Like rfind but raises ValueError when the substring is not found.
source code
string
rjust(s, width, fillchar=...)
Return a right-justified version of s, in a field of the specified width, padded with spaces as needed.
source code
list of strings
rsplit(s, sep=... , maxsplit=...)
Return a list of the words in the string s, using sep as the delimiter string, starting at the end of the string and working to the front.
source code
string
rstrip(s, chars=...)
Return a copy of the string s with trailing whitespace removed.
source code
list of strings
split(s, sep=... , maxsplit=...)
Return a list of the words in the string s, using sep as the delimiter string.
source code
list of strings
splitfields(s, sep=... , maxsplit=...)
Return a list of the words in the string s, using sep as the delimiter string.
source code
string
strip(s, chars=...)
Return a copy of the string s with leading and trailing whitespace removed.
source code
string
swapcase(s)
Return a copy of the string s with upper case characters converted to lowercase and vice versa.
source code
string
translate(s, table, deletions=...)
Return a copy of the string s, where all characters occurring in the optional argument deletions are removed, and the remaining characters have been mapped through the given translation table, which must be a string of length 256.
source code
string
upper(s)
Return a copy of the string s converted to uppercase.
source code
string
zfill(x, width)
Pad a numeric string x with zeros on the left, to fill a field of the specified width.
source code
Variables [hide private]
  _idmap = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x...
  _idmapL = None
  ascii_letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRS...
  ascii_lowercase = 'abcdefghijklmnopqrstuvwxyz'
  ascii_uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  digits = '0123456789'
  hexdigits = '0123456789abcdefABCDEF'
  letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  lowercase = 'abcdefghijklmnopqrstuvwxyz'
  octdigits = '01234567'
  printable = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLM...
  punctuation = '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'
  uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  whitespace = '\t\n\x0b\x0c\r '
Function Details [hide private]

atoi(s, base=...)

source code 

Return the integer represented by the string s in the given base, which defaults to 10. The string s must consist of one or more digits, possibly preceded by a sign. If base is 0, it is chosen from the leading characters of s, 0 for octal, 0x or 0X for hexadecimal. If base is 16, a preceding 0x or 0X is accepted.

Returns: int

atol(s, base=...)

source code 

Return the long integer represented by the string s in the given base, which defaults to 10. The string s must consist of one or more digits, possibly preceded by a sign. If base is 0, it is chosen from the leading characters of s, 0 for octal, 0x or 0X for hexadecimal. If base is 16, a preceding 0x or 0X is accepted. A trailing L or l is not accepted, unless base is 0.

Returns: long

capwords(s, sep=None)

source code 

capwords(s, [sep]) -> string

Split the argument into words using split, capitalize each word using capitalize, and join the capitalized words using join. Note that this replaces runs of whitespace characters by a single space.

center(s, width, fillchar=...)

source code 

Return a center version of s, in a field of the specified width. padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces.

Returns: string

count(s, sub, start=..., end=...)

source code 

Return the number of occurrences of substring sub in string s[start:end]. Optional arguments start and end are interpreted as in slice notation.

Returns: int

find(s, sub, start=... , end=...)

source code 

Return the lowest index in s where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation.

Return -1 on failure.

Returns: in

join(list, sep=...)

source code 

Return a string composed of the words in list, with intervening occurrences of sep. The default separator is a single space.

(joinfields and join are synonymous)

Returns: string

joinfields(list, sep=...)

source code 

Return a string composed of the words in list, with intervening occurrences of sep. The default separator is a single space.

(joinfields and join are synonymous)

Returns: string

ljust(s, width, fillchar=...)

source code 

Return a left-justified version of s, in a field of the specified width, padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces.

Returns: string

lstrip(s, chars=...)

source code 

Return a copy of the string s with leading whitespace removed. If chars is given and not None, remove characters in chars instead.

Returns: string

replace(s, old, new, maxsplit=-1)

source code 

replace (str, old, new[, maxsplit]) -> string

Return a copy of string str with all occurrences of substring old replaced by new. If the optional argument maxsplit is given, only the first maxsplit occurrences are replaced.

rfind(s, sub, start=... , end=...)

source code 

Return the highest index in s where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation.

Return -1 on failure.

Returns: int

rjust(s, width, fillchar=...)

source code 

Return a right-justified version of s, in a field of the specified width, padded with spaces as needed. The string is never truncated. If specified the fillchar is used instead of spaces.

Returns: string

rsplit(s, sep=... , maxsplit=...)

source code 

Return a list of the words in the string s, using sep as the delimiter string, starting at the end of the string and working to the front. If maxsplit is given, at most maxsplit splits are done. If sep is not specified or is None, any whitespace string is a separator.

Returns: list of strings

rstrip(s, chars=...)

source code 

Return a copy of the string s with trailing whitespace removed. If chars is given and not None, remove characters in chars instead.

Returns: string

split(s, sep=... , maxsplit=...)

source code 

Return a list of the words in the string s, using sep as the delimiter string. If maxsplit is given, splits at no more than maxsplit places (resulting in at most maxsplit+1 words). If sep is not specified or is None, any whitespace string is a separator.

(split and splitfields are synonymous)

Returns: list of strings

splitfields(s, sep=... , maxsplit=...)

source code 

Return a list of the words in the string s, using sep as the delimiter string. If maxsplit is given, splits at no more than maxsplit places (resulting in at most maxsplit+1 words). If sep is not specified or is None, any whitespace string is a separator.

(split and splitfields are synonymous)

Returns: list of strings

strip(s, chars=...)

source code 

Return a copy of the string s with leading and trailing whitespace removed. If chars is given and not None, remove characters in chars instead. If chars is unicode, S will be converted to unicode before stripping.

Returns: string

translate(s, table, deletions=...)

source code 

Return a copy of the string s, where all characters occurring in the optional argument deletions are removed, and the remaining characters have been mapped through the given translation table, which must be a string of length 256. The deletions argument is not allowed for Unicode strings.

Returns: string

zfill(x, width)

source code 

Pad a numeric string x with zeros on the left, to fill a field of the specified width. The string x is never truncated.

Returns: string

Variables Details [hide private]

_idmap

Value:
'''\x00\x01\x02\x03\x04\x05\x06\x07\x08\t
\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\
\x1d\x1e\x1f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWX\
YZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x8\
6\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\\
x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa\
9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\\
xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xc\
...

ascii_letters

Value:
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

printable

Value:
'''0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%\
&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t
\r\x0b\x0c'''

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.extension-module.html0000664000076400007640000000453011122067144025360 0ustar stefanstefan extension

Module extension


Classes

Extension

Functions

get_class_arguments
get_class_arguments_as_dictionary
get_class_description
get_extension_class_name
make_dom_document
make_dom_element
parse_descriptor
parse_dom_element
read_extension_file
validate_arguments
write_extension_file

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-C.html0000664000076400007640000006103511122067144024274 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

C



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_database.FileDatabase-class.html0000664000076400007640000016734711122067150030442 0ustar stefanstefan qm.test.file_database.FileDatabase
Package qm :: Package test :: Module file_database :: Class FileDatabase
[hide private]
[frames] | no frames]

Class FileDatabase

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
      database.Database --+
                          |
                         FileDatabase
Known Subclasses:

A 'FileDatabase' stores each test as a single file.

A 'FileDatabase' is a 'Database' that stores each test, suite, or resource as a single file. In addition, some subdirectories can be considered implicit suites. The contents of the implicit suite are all of the tests and suites contained in the subdirectory.

'FileDatabase' is an abstract class.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
GetTest(self, test_id)
Return the 'TestDescriptor' for the test named 'test_id'.
source code
 
GetTestPath(self, test_id)
Return the file containing 'test_id'.
source code
 
_IsTestFile(self, path)
Returns true if 'path' is a test file.
source code
 
GetSuite(self, suite_id)
Return the 'Suite' for the suite named 'suite_id'.
source code
 
GetSuitePath(self, suite_id)
Return the file containing 'suite_id'.
source code
 
_IsSuiteFile(self, path)
Returns true if 'path' is a test suite file or directory.
source code
 
GetResource(self, resource_id)
Return the 'ResourceDescriptor' for the resource named 'resource_id'.
source code
 
GetResourcePath(self, resource_id)
Return the file containing 'resource_id'.
source code
 
_IsResourceFile(self, path)
Returns true if 'path' is a resource file.
source code
 
GetRoot(self)
Return the root of the test database.
source code
 
GetSubdirectories(self, directory)
Return the subdirectories of 'directory'.
source code
 
GetIds(self, kind, directory='', scan_subdirs=1)
Return all IDs of the indicated 'kind' that begin with 'directory'.
source code
 
_GetPath(self, kind, id)
Returns the file system path corresponding to 'id'.
source code
 
_IsFile(self, kind, path)
Returns true if 'path' is a file of the indicated 'kind'.
source code
 
_GetTestFromPath(self, test_id, path)
Return a descriptor for the test given by 'path'.
source code
 
_GetSuiteFromPath(self, suite_id, path)
Return a the 'Suite' given by 'path'.
source code
 
_GetResourceFromPath(self, resource_id, path)
Return a descriptor for the resource given by 'path'.
source code
 
_GetPathFromLabel(self, label)
Returns the file system path corresponding to 'label'.
source code
 
_GetLabelFromBasename(self, basename)
Returns the label associated with a file named 'basename'.
source code
 
_GetLabels(self, directory, scan_subdirs, label, predicate)
Returns the labels of entities in 'directory'.
source code
 
RemoveExtension(self, id, kind)
Remove the extension 'id' from the database.
source code
 
_AreLabelsPaths(self)
Returns true if labels are to be thought of as file names.
source code
 
_GetRelativeLabelPath(self, label)
Returns a representation of 'label' as a relative filename.
source code

Inherited from database.Database: ExpandIds, GetAttachmentStore, GetClassPaths, GetConfigurationDirectory, GetExtension, GetExtensions, GetItem, GetLabelComponents, GetPath, GetResourceClassNames, GetResourceIds, GetSuiteIds, GetTestClassNames, GetTestIds, HasResource, HasSuite, HasTest, IsModifiable, IsValidLabel, JoinLabels, SplitLabel, SplitLabelLeft, WriteExtension, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  _argument_list = [<<class 'qm.fields.TextField'> label_class>,...
A list of all the 'Field's in this class.

Inherited from database.Database: ITEM_KINDS, RESOURCE, SUITE, TEST, arguments, kind, label_class, modifiable

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

GetTest(self, test_id)

source code 

Return the 'TestDescriptor' for the test named 'test_id'.

'test_id' -- A label naming the test.

returns -- A 'TestDescriptor' corresponding to 'test_id'.

raises -- 'NoSuchTestError' if there is no test in the database named 'test_id'.

Overrides: database.Database.GetTest

GetTestPath(self, test_id)

source code 

Return the file containing 'test_id'.

'test_id' -- The name of a test.

returns -- The absolute file name of the file that contains, or would contain, 'test_id'. This method works even if no test named 'test_id' exists.

Derived classes may override this method.

_IsTestFile(self, path)

source code 

Returns true if 'path' is a test file.

'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels.

returns -- True iff the file corresponds to a test.

Derived classes must override this method.

GetSuite(self, suite_id)

source code 

Return the 'Suite' for the suite named 'suite_id'.

'suite_id' -- A label naming the suite.

returns -- An instance of 'Suite' (or a derived class of 'Suite') corresponding to 'suite_id'.

raises -- 'NoSuchSuiteError' if there is no suite in the database named 'suite_id'.

Overrides: database.Database.GetSuite

GetSuitePath(self, suite_id)

source code 

Return the file containing 'suite_id'.

'suite_id' -- The name of a suite.

returns -- The absolute file name of the file (or directory) that contains, or would contain, 'suite_id'. This method works even if no suite named 'suite_id' exists.

Derived classes may override this method.

_IsSuiteFile(self, path)

source code 

Returns true if 'path' is a test suite file or directory.

'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels.

returns -- True iff the file corresponds to a test.

Derived classes may override this method, but only to restrict the set of suites. In particular, a derived class method may return false where this method would return true, but never vice versa.

Derived classes must override this method.

GetResource(self, resource_id)

source code 

Return the 'ResourceDescriptor' for the resource named 'resource_id'.

'resource_id' -- A label naming the resource.

returns -- A 'ResourceDescriptor' corresponding to 'resource_id'.

raises -- 'NoSuchResourceError' if there is no resource in the database named 'resource_id'.

Overrides: database.Database.GetResource

GetResourcePath(self, resource_id)

source code 

Return the file containing 'resource_id'.

'resource_id' -- The name of a resource.

returns -- The absolute file name of the file that contains, or would contain, 'resource_id'. This method works even if no Resource named 'resource_id' exists.

Derived classes may override this method.

_IsResourceFile(self, path)

source code 

Returns true if 'path' is a resource file.

'path' -- The absolute name of a file. All relevant components in the path name have already been checked to ensure that they are valid labels.

returns -- True iff the file corresponds to a resource.

Derived classes must override this method.

GetRoot(self)

source code 

Return the root of the test database.

returns -- The directory that serves as the root of the test database. All paths are relative to this directory.

Derived classes may override this method.

GetSubdirectories(self, directory)

source code 

Return the subdirectories of 'directory'.

'directory' -- A label indicating a directory in the database.

returns -- A sequence of (relative) labels indictating the subdirectories of 'directory'. For example, if "a.b" and "a.c" are directories in the database, this method will return "b" and "c" given "a" as 'directory'.

Overrides: database.Database.GetSubdirectories

GetIds(self, kind, directory='', scan_subdirs=1)

source code 

Return all IDs of the indicated 'kind' that begin with 'directory'.

'kind' -- One of the 'ITEM_KINDS'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

returns -- A list of all items of the indicated 'kind' located within 'directory', as absolute labels.

Derived classes may override this method.

Overrides: database.Database.GetIds
(inherited documentation)

_GetPath(self, kind, id)

source code 

Returns the file system path corresponding to 'id'.

'kind' -- An extension kind.

'id' -- The name of the entity.

returns -- The path in which the entity is stored.

_IsFile(self, kind, path)

source code 

Returns true if 'path' is a file of the indicated 'kind'.

'kind' -- One of 'Database.ITEM_KINDS'.

'path' -- The path to a file.

returns -- True iff 'path' is a file of the indicated kind.

Derived classes must override this method.

_GetTestFromPath(self, test_id, path)

source code 

Return a descriptor for the test given by 'path'.

'test_id' -- The label naming the test.

'path' -- An absolute path to a test file. The 'path' satisfies '_IsTestFile'.

returns -- A 'TestDescriptor' corresponding to 'test_id'.

Derived classes must override this method.

_GetSuiteFromPath(self, suite_id, path)

source code 

Return a the 'Suite' given by 'path'.

'suite_id' -- The label naming the suite.

'path' -- An absolute path to a suite file. The 'path' satisfies '_IsSuiteFile' and is a file, not a directory.

returns -- A 'Suite' corresponding to 'suite_id'.

Derived classes must override this method.

_GetResourceFromPath(self, resource_id, path)

source code 

Return a descriptor for the resource given by 'path'.

'resource_id' -- The label naming the resource.

'path' -- An absolute path to a resource file. The 'path' satisfies '_IsResourceFile'.

returns -- A 'ResourceDescriptor' corresponding to 'resource_id'.

Derived classes must override this method.

_GetPathFromLabel(self, label)

source code 

Returns the file system path corresponding to 'label'.

'label' -- The id for a test, test suite, or similar entity.

returns -- The absolute path for the corresponding entry in the file system, but without any required extension.

_GetLabelFromBasename(self, basename)

source code 

Returns the label associated with a file named 'basename'.

'basename' -- The basename of a file, including the extension.

returns -- The corresponding label.

Derived classes may override this method.

_GetLabels(self, directory, scan_subdirs, label, predicate)

source code 

Returns the labels of entities in 'directory'.

'directory' -- The absolute path name of the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

'label' -- The label that corresponds to 'directory'.

'predicate' -- A function that takes a file name and returns a boolean.

returns -- Labels for all file names in 'directory'. that satisfy 'predicate' If 'scan_subdirs' is true, subdirectories are scanned as well.

RemoveExtension(self, id, kind)

source code 

Remove the extension 'id' from the database.

'id' -- A label for the 'Extension' instance stored in the database.

'kind' -- The kind of 'Extension' stored with the given 'id'.

Overrides: database.Database.RemoveExtension
(inherited documentation)

_AreLabelsPaths(self)

source code 

Returns true if labels are to be thought of as file names.

returns -- True if labels are to be thought of as file names. If this predicate holds, every label is a path, relative to the root of the database. If false, the labels are translated to paths by adding the 'suite_extension' between directories and the 'test_extension' or 'resource_extension' at the end of the name.

_GetRelativeLabelPath(self, label)

source code 

Returns a representation of 'label' as a relative filename.

returns -- A relative filename corresponding to 'label'.


Class Variable Details [hide private]

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.TextField'> label_class>,
 <<class 'qm.fields.BooleanField'> modifiable>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html0000664000076400007640000006461611122067146032206 0ustar stefanstefan qm.external.DocumentTemplate.DT_HTML.HTMLFile
Package qm :: Package external :: Package DocumentTemplate :: Module DT_HTML :: Class HTMLFile
[hide private]
[frames] | no frames]

Class HTMLFile

source code

 DT_String.FileMixin --+
                       |
DT_String.String --+   |
                   |   |
                HTML --+
                       |
                      HTMLFile

HTML Document templates read from files.

If the object is pickled, the file name, rather than the file contents is pickled. When the object is unpickled, then the file will be re-read to obtain the string. Note that the file will not be read until the document template is used the first time.

Instance Methods [hide private]
 
manage_default(self, REQUEST=None)
Revert to factory defaults
source code
 
manage_editForm(self, URL1, REQUEST)
Display doc template editing form
source code
 
manage(self, URL1, REQUEST)
Display doc template editing form
source code
 
manage_editDocument(self, URL1, REQUEST)
Display doc template editing form
source code
 
manage_edit(self, data, PARENTS=[], URL1='', URL2='', REQUEST='', SUBMIT='')
edit a template
source code

Inherited from DT_String.FileMixin: __init__, read_raw

Inherited from HTML: SubTemplate, __str__, errQuote, management_interface, parseTag, quotedHTML, tagre, varExtra

Inherited from DT_String.String: ZDocumentTemplate_afterRender, ZDocumentTemplate_beforeRender, __call__, __getstate__, cook, default, id, initvars, munge, name, parse, parse_block, parse_close, parse_error, read, setName, skip_eol, var

Inherited from DT_String.String (private): _parseTag

Class Variables [hide private]
  manage_default__roles__ = ()
  manage_editForm__roles__ = ()
  manage_editDocument__roles__ = ()
  manage__roles__ = ()
  manage_edit__roles__ = ()

Inherited from DT_String.FileMixin: edited_source, read_raw__roles__

Inherited from HTML: SubTemplate__roles__, errQuote__roles__, management_interface__roles__, parseTag__roles__, quotedHTML__roles__, tagre__roles__, varExtra__roles__

Inherited from DT_String.String: ZDocumentTemplate_afterRender__roles__, ZDocumentTemplate_beforeRender__roles__, _parseTag__roles__, commands, commands__roles__, cook__roles__, default__roles__, func_code, func_defaults, func_defaults__roles__, initvars__roles__, isDocTemp, munge__roles__, parse__roles__, parse_block__roles__, parse_close__roles__, parse_error__roles__, read__roles__, setName__roles__, shared_globals, shared_globals__roles__, skip_eol__roles__, validate, validate__roles__, var__roles__

Method Details [hide private]

manage_editForm(self, URL1, REQUEST)

source code 

Display doc template editing form

Overrides: HTML.manage_editForm

manage(self, URL1, REQUEST)

source code 

Display doc template editing form

Overrides: HTML.manage_editForm

manage_editDocument(self, URL1, REQUEST)

source code 

Display doc template editing form

Overrides: HTML.manage_editForm

manage_edit(self, data, PARENTS=[], URL1='', URL2='', REQUEST='', SUBMIT='')

source code 

edit a template

Overrides: DT_String.String.manage_edit

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.cmdline-module.html0000664000076400007640000002453611122067145025163 0ustar stefanstefan qm.test.cmdline
Package qm :: Package test :: Module cmdline
[hide private]
[frames] | no frames]

Module cmdline

source code

Classes [hide private]
  QMTest
An instance of QMTest.
Functions [hide private]
 
_make_comma_separated_string(items, conjunction)
Return a string consisting of the 'items', separated by commas.
source code
 
get_qmtest()
Returns the global QMTest object.
source code
Variables [hide private]
  _the_qmtest = None
The global 'QMTest' object.
Function Details [hide private]

_make_comma_separated_string(items, conjunction)

source code 

Return a string consisting of the 'items', separated by commas.

'items' -- A list of strings giving the items in the list.

'conjunction' -- A string to use before the final item, if there is more than one.

returns -- A string consisting all of the 'items', separated by commas, and with the 'conjunction' before the final item.

get_qmtest()

source code 

Returns the global QMTest object.

returns -- The 'QMTest' object that corresponds to the currently executing thread.

At present, there is only one QMTest object per process. In the future, however, there may be more than one. Then, this function will return different values in different threads.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command_host-module.html0000664000076400007640000001127711122067145027655 0ustar stefanstefan qm.test.classes.command_host
Package qm :: Package test :: Package classes :: Module command_host
[hide private]
[frames] | no frames]

Module command_host

source code

Classes [hide private]
  CommandHost
A CommandHost runs an executable through a command.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.common.PythonException-class.html0000664000076400007640000002306411122067145027034 0ustar stefanstefan qm.common.PythonException
Package qm :: Module common :: Class PythonException
[hide private]
[frames] | no frames]

Class PythonException

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
                     QMException --+
                                   |
                                  PythonException

A 'PythonException' is a wrapper around a Python exception.

A 'PythonException' is a 'QMException' and, as such, can be processed by the QM error-handling routines. However, the raw Python exception which triggered this exception can be obtained by using the 'exc_type' and 'exc_value' attributes of this exception.

Instance Methods [hide private]
 
__init__(self, message, exc_type, exc_value)
Construct a new 'PythonException'.
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, message, exc_type, exc_value)
(Constructor)

source code 

Construct a new 'PythonException'.

'message' -- A string describing the cause of the message as structured text. If this exception is not handled, the 'message' will be displayed as an error message.

'exc_type' -- The type of the Python exception.

'exc_value' -- The value of the Python exception.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.XmlDatabase-class.html0000664000076400007640000002352611122067151025547 0ustar stefanstefan qm.user.XmlDatabase
qm :: user :: XmlDatabase :: Class XmlDatabase
[hide private]
[frames] | no frames]

Class XmlDatabase

source code

An XML user database.

An object of this class behaves as a read-only map from user IDs to 'User' objects.

Instance Methods [hide private]
 
__init__(self, database_path)
Read in the XML user database.
source code
 
GetDefaultUserId(self)
Return the ID of the default user, or 'None'.
source code
 
GetGroupIds(self)
Return the IDs of user groups.
source code
 
GetGroup(self, group_id)
Return the group with ID 'group_id'.
source code
 
Write(self)
Write out the user database.
source code
 
__getitem__(self, user_id) source code
 
get(self, user_id, default=None) source code
 
keys(self) source code
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.web-module.html0000664000076400007640000000167711122067144025110 0ustar stefanstefan web

Module web



[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.run_database.RunDatabase-class.html0000664000076400007640000005456711122067150030213 0ustar stefanstefan qm.test.run_database.RunDatabase
Package qm :: Package test :: Module run_database :: Class RunDatabase
[hide private]
[frames] | no frames]

Class RunDatabase

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     RunDatabase

A 'RunDatabase' stores 'TestRun's.

A 'RunDatabase' provides a mechanism for selecting 'TestRun's that meet particular criteria.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
GetAllRuns(self)
Return all the 'TestRun's in the database.
source code
 
GetRuns(self, predicate)
Return the set of 'TestRun's satisfying 'predicate'
source code
 
GetAnnotations(self, key)
Return the set of annotations for 'key' from all test runs.
source code
 
GetTimeframe(self, time_key, is_iso_time=True)
Return a pair of min / max values found for the given time_key across all test runs.
source code
 
GetRunInTimeframe(self, key, value, time_key, minimum, maximum, is_iso_time=True)
Return a test run id matching the key and timeframe.
source code
 
GetRunsByAnnotations(self, annotation_filter)
Return the 'TestRun's matching 'annotation_filter'.
source code
 
GetOutcomes(self, id, kind='test')
Return an outcome dictionary for the indicated test.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__, __init__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from extension.Extension: arguments, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

GetAllRuns(self)

source code 

Return all the 'TestRun's in the database.

returns -- A sequence consisting of all of the 'TestRun's in the database.

GetRuns(self, predicate)

source code 

Return the set of 'TestRun's satisfying 'predicate'

'predicate' -- A callable that can be passed one 'TestRun' argument.

returns -- A sequence of 'TestRun's consisting only of those 'TestRun's in the database for which 'predicate' returns a true value.

GetAnnotations(self, key)

source code 

Return the set of annotations for 'key' from all test runs.

'key' -- A string used to look up the annotations.

returns -- A set of (distinct) annotations for 'key' from all test runs.

GetTimeframe(self, time_key, is_iso_time=True)

source code 

Return a pair of min / max values found for the given time_key across all test runs.

'time_key' -- Annotation key referring to a string convertible to either iso-formatted time or floating point number.

returns -- minimum, maximum.

GetRunsByAnnotations(self, annotation_filter)

source code 

Return the 'TestRun's matching 'annotation_filter'.

'annotation_filter' -- A dictionary mapping annotation keys (strings) to values (either strings or callables).

returns -- A sequence of 'TestRun's consisting only of those 'TestRun's in the database that match the 'annotation_filter'. A 'TestRun' matches the 'annotation_filter' if it matches each of the key-value pairs in the filter. If the value in such a pair is a string, then the annotation in the 'TestRun' must exactly match the value. If the value is a callable, rather than a string, then when passed the value from the 'TestRun', the predicate must return a true value.

GetOutcomes(self, id, kind='test')

source code 

Return an outcome dictionary for the indicated test.

'id' -- The name of a test, suite, or resource item.

'kind' -- The kind of the item to retrieve the outcome for.

returns -- A dictionary indicating the number of outcomes per category.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.common.QMException-class.html0000664000076400007640000002357611122067145026100 0ustar stefanstefan qm.common.QMException
Package qm :: Module common :: Class QMException
[hide private]
[frames] | no frames]

Class QMException

source code

              object --+        
                       |        
exceptions.BaseException --+    
                           |    
        exceptions.Exception --+
                               |
                              QMException
Known Subclasses:

An exception generated directly by QM.

All exceptions thrown by QM should be derived from this class.

Instance Methods [hide private]
 
__init__(self, message)
Construct a new 'QMException'.
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, message)
(Constructor)

source code 

Construct a new 'QMException'.

'message' -- A string describing the cause of the message as structured text. If this exception is not handled, the 'message' will be displayed as an error message.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.context-module.html0000664000076400007640000000242711122067144026011 0ustar stefanstefan context

Module context


Classes

Context
ContextException
ContextWrapper

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.Database-class.html0000664000076400007640000024370711122067150026636 0ustar stefanstefan qm.test.database.Database
qm :: test :: database :: Database :: Class Database
[hide private]
[frames] | no frames]

Class Database

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     Database
Known Subclasses:

A 'Database' stores tests, testsuites, and resources.

A 'Database' has two primary functions:

1. Test storage and retrieval.

   Every test has a unique name, called a "test id". When a new 
   test is created, the 'Database' is responsible for writing that
   test to permanent storage.  Later, QMTest will request the test 
   by providing the database with the test id.  The database must
   retrieve the test from permanent storage.

   QMTest does not put any restrictions on *how* tests are stored.
   The default database implementation uses XML to store tests,
   but any storage format will do.

2. Test enumeration.

   The 'Database' can tell QMTest what tests are stored in the
   database.  QMTest uses this information in its graphical user
   interface to show the user what tests exist.
   
A 'Database' stores testsuites and resources in addition to tests.
The names for tests, testsuites, and resources are all "labels".  A
label is a special kind of string that is designed to be easily
convertible to a file name.  For more information, see the
'qm.label' module.  The namespaces for tests, testsuites, and
resources are all distinct.  For example, it is OK to have a test
with the same name as a testsuite.

Every 'Database' is associated with a particular directory on the
local machine.  In most cases, the 'Database' will store all the
files it needs within this directory.

Every 'Database' has an associated 'AttachmentStore'.  An
'AttachmentStore' is responsible for storing the attachments
associated with tests.  See the module 'qm.attachment' for more
information about 'AttachmentStore'.

'Database' is an abstract class.

You can extend QMTest by providing your own database implementation.
One reason to do this is that you may want to store tests in a
format different from the XML format that QMTest uses by default.
For example, if you are testing a compiler, you might want to
represent each test as a source file.  Or, if you are testing a
SQL database, you might want to represent each test as two files:
one containing SQL commands to run the test, and one containing
the output you expect.

Another reason to provide your own database implementation is that
you might want to store tests on a remote location.  For example,
suppose you wanted to allow multiple users to access the same 
central test database.  You could create a test database that
created and retrieved tests by communicating with the central
server.

To create your own database implementation, you must create a Python
class derived (directly or indirectly) from 'Database'.  The
documentation for each method of 'Database' indicates whether you
must override it in your database implementation.  Some methods may
be overridden, but do not need to be.  You might want to override
such a method to provide a more efficient implementation, but QMTest
will work fine if you just use the default version.

If QMTest calls a method on a database and that method raises an
exception that is not caught within the method itself, QMTest will
catch the exception and continue processing.  Therefore, methods
here only have to handle exceptions themselves if that is necessary
to maintain the integrity of the database.

A single 'Database' may be accessed by multiple threads
simultaneously.  Therefore, you must take appropriate steps to
ensure thread-safe access to shared data.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, path, arguments=None, **args)
Construct a 'Database'.
source code
 
IsValidLabel(self, label, is_component=1)
Return true if 'label' is valid.
source code
 
JoinLabels(self, *labels)
Join the 'labels' together.
source code
 
SplitLabel(self, label)
Split the label into a pair '(directory, basename)'.
source code
 
SplitLabelLeft(self, label)
Split the label into a pair '(parent, subpath)'.
source code
 
GetLabelComponents(self, label)
Return all of the component directories of 'label'.
source code
 
GetExtension(self, id)
Return the extension object named 'id'.
source code
 
GetExtensions(self, directory, scan_subdirs)
Return the extensions in 'directory'.
source code
 
RemoveExtension(self, id, kind)
Remove the extension 'id' from the database.
source code
 
WriteExtension(self, id, extension)
Store 'extension' in the database, using the name 'id'.
source code
 
GetTest(self, test_id)
Return the 'TestDescriptor' for the test named 'test_id'.
source code
 
HasTest(self, test_id)
Check whether or not the database has a test named 'test_id'.
source code
 
GetTestIds(self, directory='', scan_subdirs=1)
Return all test IDs that begin with 'directory'.
source code
 
GetSuite(self, suite_id)
Return the 'Suite' for the suite named 'suite_id'.
source code
 
HasSuite(self, suite_id)
Check whether or not the database has a suite named 'suite_id'.
source code
 
GetSuiteIds(self, directory='', scan_subdirs=1)
Return all suite IDs that begin with 'directory'.
source code
 
GetResource(self, resource_id)
Return the 'ResourceDescriptor' for the resource 'resouce_id'.
source code
 
HasResource(self, resource_id)
Check whether or not the database has a resource named 'resource_id'.
source code
 
GetResourceIds(self, directory='', scan_subdirs=1)
Return all resource IDs that begin with 'directory'.
source code
 
GetIds(self, kind, directory='', scan_subdirs=1)
Return all IDs of the indicated 'kind' that begin with 'directory'.
source code
 
GetItem(self, kind, item_id)
Return the item of the indicated 'kind' with indicated 'item_id'.
source code
 
GetSubdirectories(self, directory)
Return the immediate subdirectories of 'directory'.
source code
 
GetPath(self)
Return the directory containing the database.
source code
 
GetConfigurationDirectory(self)
Return the directory containing configuration information.
source code
 
GetAttachmentStore(self)
Returns the 'AttachmentStore' associated with the database.
source code
 
GetClassPaths(self)
Return directories to search for test and resource classes.
source code
 
GetTestClassNames(self)
Return the kinds of tests that the database can store.
source code
 
GetResourceClassNames(self)
Return the kinds of resources that the database can store.
source code
 
ExpandIds(self, ids)
Expand test and suite IDs into test IDs.
source code
 
IsModifiable(self)
Returns true iff this database is modifiable.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.fields.TextField'> label_class>, <<cl...
A list of the arguments to the extension class.
  RESOURCE = 'resource'
  SUITE = 'suite'
  TEST = 'test'
  ITEM_KINDS = ['resource', 'suite', 'test']
The kinds of items that can be stored in a 'Database'.
  _item_exceptions = {'resource': <class 'qm.test.database.NoSuc...
The exceptions to be raised when a particular item cannot be found.
  _is_generic_database = False
True if this database implements 'GetExtension' as a primitive.
  kind = 'database'
The 'Extension' kind.
  _argument_dictionary = {'label_class': <<class 'qm.fields.Text...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.BooleanField'> modifiable...
A list of all the 'Field's in this class.
  label_class = 'python_label.PythonLabel'
  modifiable = 'true'
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, path, arguments=None, **args)
(Constructor)

source code 

Construct a 'Database'.

'path' -- A string containing the absolute path to the directory containing the database.

'arguments' -- A dictionary mapping attribute names to values. The use of this parameter is deprecated. Use keyword arguments instead.

Derived classes must call this method from their own '__init__' methods. Every derived class must have an '__init__' method that takes the path to the directory containing the database as its only argument. The path provided to the derived class '__init__' function will always be an absolute path.

Overrides: object.__init__

IsValidLabel(self, label, is_component=1)

source code 

Return true if 'label' is valid.

'label' -- A string that is being considered as a label.

'is_component' -- True if the string being tested is just a single component of a label path.

returns -- True if 'label' is a valid name for entities in this database.

JoinLabels(self, *labels)

source code 

Join the 'labels' together.

'labels' -- A sequence of strings corresponding to label components.

returns -- A string containing the complete label.

SplitLabel(self, label)

source code 

Split the label into a pair '(directory, basename)'.

returns -- A pair of strings '(directory, basename)'.

SplitLabelLeft(self, label)

source code 

Split the label into a pair '(parent, subpath)'. This is the same operation as SplitLabel, except the split occurs at the leftmost separator, not the rightmost, and a single-component label comes back in the parent slot.

returns -- A pair of strings '(parent, subpath)'.

GetLabelComponents(self, label)

source code 

Return all of the component directories of 'label'.

'label' -- A string naming an entity in the database.

returns -- A list of strings. The first string is the first directory in 'label'; the last string is the basename.

GetExtension(self, id)

source code 

Return the extension object named 'id'.

'id' -- The label for the extension.

returns -- The instance of 'Extension' with the indicated name, or 'None' if there is no such entity.

Database classes should override this method. For backwards compatibility, this base class implements this generic method in terms of the special-purpose methods 'GetTest()' and 'GetResource()'. Only if _is_generic_database is True are these implemented in terms of 'GetExtension()'.

GetExtensions(self, directory, scan_subdirs)

source code 

Return the extensions in 'directory'.

'directory' -- The name of a directory.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

returns -- A dictionary mapping labels to 'Extension' instances. The dictionary contains all extensions in 'directory', and, if 'scan_subdirs' is true, its subdirectories.

RemoveExtension(self, id, kind)

source code 

Remove the extension 'id' from the database.

'id' -- A label for the 'Extension' instance stored in the database.

'kind' -- The kind of 'Extension' stored with the given 'id'.

WriteExtension(self, id, extension)

source code 

Store 'extension' in the database, using the name 'id'.

'id' -- A label for the 'extension'.

'extension' -- An instance of 'Extension'.

The 'extension' is stored in the database. If there is a previous item in the database with the same id, it is removed and replaced with 'extension'. Some databases may not be able to store all 'Extension' instances; those database must throw an exception when an attempt is made to store such an 'extension'.

GetTest(self, test_id)

source code 

Return the 'TestDescriptor' for the test named 'test_id'.

'test_id' -- A label naming the test.

returns -- A 'TestDescriptor' corresponding to 'test_id'.

raises -- 'NoSuchTestError' if there is no test in the database named 'test_id'.

HasTest(self, test_id)

source code 

Check whether or not the database has a test named 'test_id'.

'test_id' -- A label naming the test.

returns -- True if and only if the database contains a test named 'test_id'. If this function returns true, 'GetTest' will usually succeed. However, they may be circumstances where 'HasTest' returns true and 'GetTest' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasTest' is called and the time that 'GetTest' is called.

Derived classes may override this method.

GetTestIds(self, directory='', scan_subdirs=1)

source code 

Return all test IDs that begin with 'directory'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

'returns' -- A list of all tests located within 'directory', as absolute labels.

GetSuite(self, suite_id)

source code 

Return the 'Suite' for the suite named 'suite_id'.

'suite_id' -- A label naming the suite.

returns -- An instance of 'Suite' (or a derived class of 'Suite') corresponding to 'suite_id'.

raises -- 'NoSuchSuiteError' if there is no test in the database named 'test_id'.

All databases must have an implicit suite called '' that contains all tests in the database. More generally, for each directory in the database, there must be a corresponding suite that contains all tests in that directory and its subdirectories.

HasSuite(self, suite_id)

source code 

Check whether or not the database has a suite named 'suite_id'.

'suite_id' -- A label naming the suite.

returns -- True if and only if the database contains a suite named 'suite_id'. If this function returns true, 'GetSuite' will usually succeed. However, they may be circumstances where 'HasSuite' returns true and 'GetSuite' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasSuite' is called and the time that 'GetSuite' is called.

All databases must have an implicit suite called "" that contains all tests in the database. More generally, for each directory in the database, there must be a corresponding suite that contains all tests in that directory and its subdirectories.

Derived classes may override this method.

GetSuiteIds(self, directory='', scan_subdirs=1)

source code 

Return all suite IDs that begin with 'directory'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

'returns' -- A list of all suites located within 'directory', as absolute labels.

GetResource(self, resource_id)

source code 

Return the 'ResourceDescriptor' for the resource 'resouce_id'.

'resource_id' -- A label naming the resource.

returns -- A 'ResourceDescriptor' corresponding to 'resource_id'.

raises -- 'NoSuchResourceError' if there is no resource in the database named 'resource_id'.

HasResource(self, resource_id)

source code 

Check whether or not the database has a resource named 'resource_id'.

'resource_id' -- A label naming the resource.

returns -- True if and only if the database contains a resource named 'resource_id'. If this function returns true, 'GetResource' will usually succeed. However, they may be circumstances where 'HasResource' returns true and 'GetResource' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasResource' is called and the time that 'GetResource' is called.

Derived classes may override this method.

GetResourceIds(self, directory='', scan_subdirs=1)

source code 

Return all resource IDs that begin with 'directory'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

'returns' -- A list of all resources located within 'directory', as absolute labels.

GetIds(self, kind, directory='', scan_subdirs=1)

source code 

Return all IDs of the indicated 'kind' that begin with 'directory'.

'kind' -- One of the 'ITEM_KINDS'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

returns -- A list of all items of the indicated 'kind' located within 'directory', as absolute labels.

Derived classes may override this method.

GetItem(self, kind, item_id)

source code 

Return the item of the indicated 'kind' with indicated 'item_id'.

'kind' -- One of the 'ITEM_KINDS'.

'item_id' -- The name of the item.

returns -- If 'kind' is 'Database.TEST' or 'Database.RESOURCE', returns a test descriptor or resource descriptor, respectively. If 'kind' is 'Database.SUITE', returns a 'Suite'.

Derived classes may override this method.

GetSubdirectories(self, directory)

source code 

Return the immediate subdirectories of 'directory'.

'directory' -- A label indicating a directory in the database.

returns -- A sequence of (relative) labels indictating the immediate subdirectories of 'directory'. For example, if "a.b" and "a.c" are directories in the database, this method will return "b" and "c" given "a" as 'directory'.

Derived classes may override this method.

GetPath(self)

source code 

Return the directory containing the database.

returns -- A string containing the absolute path to the directory containing the database.

Derived classes must not override this method.

GetConfigurationDirectory(self)

source code 

Return the directory containing configuration information.

returns -- The directory containing configuration information for the database.

Derived classes must not override this method.

GetAttachmentStore(self)

source code 

Returns the 'AttachmentStore' associated with the database.

returns -- The 'AttachmentStore' containing the attachments associated with tests and resources in this database.

Derived classes may override this method.

GetClassPaths(self)

source code 

Return directories to search for test and resource classes.

returns -- A sequence of strings. Each string is a directory that should be searched to locate test and resource classes. The directories will be searched in the order they appear. QMTest will search other directories (like those in the 'QMTEST_CLASS_PATH' environment variable) in addition to these directories.

For a given database, this method should always return the same value; callers are permitted to cache the value returned.

Derived classes may override this method. The sequence returned by the derived class need not be a superset of the value returned by the default implementation (but probably should be).

GetTestClassNames(self)

source code 

Return the kinds of tests that the database can store.

returns -- A sequence of strings. Each string names a class, including the containing module. Only classes of these types can be stored in the database.

Derived classes may override this method. The default implementation allows all available test classes, but the derived class may allow only a subset.

GetResourceClassNames(self)

source code 

Return the kinds of resources that the database can store.

returns -- A sequence of strings. Each string names a class, including the containing module. Only resources of these types can be stored in the database.

Derived classes may override this method. The default implementation allows all available resource classes, but the derived class may allow only a subset.

ExpandIds(self, ids)

source code 

Expand test and suite IDs into test IDs.

'ids' -- A sequence of IDs of tests and suites, which may be mixed together.

returns -- A pair 'test_ids, suite_ids'. 'test_ids' is a sequence of test IDs including all test IDs mentioned in 'ids' plus all test IDs obtained from recursively expanding suites included in 'ids'. 'suite_ids' is the set of IDs of suites included directly and indirectly in 'ids'.

raises -- 'ValueError' if an element in 'id' is neither a test or suite ID. The exception argument is the erroneous element.

IsModifiable(self)

source code 

Returns true iff this database is modifiable.

returns -- True iff this database is modifiable. If the database is modifiable, it supports operatings like 'Write' that make changes to the structure of the databaes itself. Otherwise, the contents of the database may be viewed, but not modified.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[<<class 'qm.fields.TextField'> label_class>,
 <<class 'qm.fields.BooleanField'> modifiable>]

_item_exceptions

The exceptions to be raised when a particular item cannot be found.

This map is indexed by the 'ITEM_KINDS'; the value indicates the exception class to be used when the indicated kind cannot be found.

Value:
{'resource': <class 'qm.test.database.NoSuchResourceError'>,
 'suite': <class 'qm.test.database.NoSuchSuiteError'>,
 'test': <class 'qm.test.database.NoSuchTestError'>}

_is_generic_database

True if this database implements 'GetExtension' as a primitive.

Databases should implement 'GetExtension' and then override '_is_generic_database', setting it to 'True'. However, legacy databases implemented 'GetTest', 'GetResource', and 'GetSuite' as primivites. These legacy databases should not override '_generic_database'.

Value:
False

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'label_class': <<class 'qm.fields.TextField'> label_class>,
 'modifiable': <<class 'qm.fields.BooleanField'> modifiable>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.BooleanField'> modifiable>,
 <<class 'qm.fields.TextField'> label_class>]

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.dist.command.build_extensions-module.html0000664000076400007640000000216611122067144031304 0ustar stefanstefan build_extensions

Module build_extensions


Classes

build_extensions

[hide private] ././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.pickle_result_stream.PickleResultReader-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.pickle_result_stream.PickleResultReader-cl0000664000076400007640000004722311122067147033322 0ustar stefanstefan qm.test.classes.pickle_result_stream.PickleResultReader
Package qm :: Package test :: Package classes :: Module pickle_result_stream :: Class PickleResultReader
[hide private]
[frames] | no frames]

Class PickleResultReader

source code

                 object --+            
                          |            
        extension.Extension --+        
                              |        
     result_reader.ResultReader --+    
                                  |    
file_result_reader.FileResultReader --+
                                      |
                                     PickleResultReader

A 'PickleResultReader' reads in results from pickle files.

See also 'PickleResultStream', which does the reverse.

Nested Classes [hide private]

Inherited from file_result_reader.FileResultReader: InvalidFile

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'FileResultReader'.
source code
 
_ResetUnpickler(self) source code
 
_ReadAddress(self) source code
 
_ReadMetadata(self) source code
 
GetAnnotations(self)
Return this run's dictionary of annotations.
source code
 
GetResult(self)
Return the next 'Result' from this reader.
source code

Inherited from result_reader.ResultReader: __iter__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from file_result_reader.FileResultReader: arguments, file, filename

Inherited from result_reader.ResultReader: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'FileResultReader'.

'arguments' -- As for 'ResultReader'.

If the file provided is not in the input format expected by this result reader, the derived class '__init__' function must raise an 'InvalidStream' exception.

Overrides: object.__init__
(inherited documentation)

GetAnnotations(self)

source code 

Return this run's dictionary of annotations.

Overrides: result_reader.ResultReader.GetAnnotations
(inherited documentation)

GetResult(self)

source code 

Return the next 'Result' from this reader.

returns -- A 'Result', or 'None' if there are no more results.

Overrides: result_reader.ResultReader.GetResult
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result-module.html0000664000076400007640000001103711122067145025056 0ustar stefanstefan qm.test.result
Package qm :: Package test :: Module result
[hide private]
[frames] | no frames]

Module result

source code

Classes [hide private]
  Result
A 'Result' describes the outcome of a test.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform_unix-module.html0000664000076400007640000003345011122067145025454 0ustar stefanstefan qm.platform_unix
Package qm :: Module platform_unix
[hide private]
[frames] | no frames]

Module platform_unix

source code

Classes [hide private]
  SignalException
An exception raised in response to a signal.
Functions [hide private]
 
open_in_browser(url)
Open a browser window and point it at 'url'.
source code
 
get_signal_name(signal_number)
Return the name for signal 'signal_number'.
source code
 
install_signal_handler(signal_number)
Install a handler to translate a signal into an exception.
source code
 
_signal_handler(signal_number, execution_frame)
Generic signal handler that raises an exception.
source code
 
get_host_name()
Return the name of this computer.
source code
 
_initialize()
Perform module initialization.
source code
Variables [hide private]
  default_shell = ['/bin/bash', '-norc', '-noprofile']
Function Details [hide private]

open_in_browser(url)

source code 

Open a browser window and point it at 'url'.

The browser is run in a separate, independent process.

get_signal_name(signal_number)

source code 

Return the name for signal 'signal_number'.

returns -- The signal's name, or 'None'.

install_signal_handler(signal_number)

source code 

Install a handler to translate a signal into an exception.

The signal handler raises a 'SignalException' exception in response to a signal.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.NoSuchResourceError-class.html0000664000076400007640000002273511122067150031047 0ustar stefanstefan qm.test.database.NoSuchResourceError
qm :: test :: database :: NoSuchResourceError :: Class NoSuchResourceError
[hide private]
[frames] | no frames]

Class NoSuchResourceError

source code

              object --+                    
                       |                    
exceptions.BaseException --+                
                           |                
        exceptions.Exception --+            
                               |            
              common.QMException --+        
                                   |        
                       DatabaseError --+    
                                       |    
                         NoSuchItemError --+
                                           |
                                          NoSuchResourceError

The specified resource does not exist.

Instance Methods [hide private]
 
__init__(self, resource_id)
Construct a new 'NoSuchResourceError'
source code

Inherited from NoSuchItemError: __str__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, resource_id)
(Constructor)

source code 

Construct a new 'NoSuchResourceError'

'resource_id' -- The name of the resource that does not exist.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.thread_target-module.html0000664000076400007640000000232611122067144030574 0ustar stefanstefan thread_target

Module thread_target


Classes

LocalThread
ThreadTarget

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_Return-module.html0000664000076400007640000000232411122067144032303 0ustar stefanstefan DT_Return

Module DT_Return


Classes

DTReturn
ReturnTag

[hide private] ././@LongLink0000000000000000000000000000015300000000000011564 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command.install_extensions.install_extensions-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command.install_extensions.install_extensions-clas0000664000076400007640000003210011122067146033477 0ustar stefanstefan qm.dist.command.install_extensions.install_extensions
Package qm :: Package dist :: Package command :: Module install_extensions :: Class install_extensions
[hide private]
[frames] | no frames]

Class install_extensions

source code

                distutils.cmd.Command --+    
                                        |    
distutils.command.install_lib.install_lib --+
                                            |
                                           install_extensions

Install extension files.

Instance Methods [hide private]
 
finalize_options(self)
Set final values for all the options that this command supports.
source code
 
run(self)
A command's raison d'etre: carry out the action it exists to perform, controlled by the options initialized in 'initialize_options()', customized by other commands, the setup script, the command-line, and config files, and finalized in 'finalize_options()'.
source code

Inherited from distutils.command.install_lib.install_lib: build, byte_compile, get_inputs, get_outputs, initialize_options, install

Inherited from distutils.command.install_lib.install_lib (private): _bytecode_filenames, _mutate_outputs

Inherited from distutils.cmd.Command: __getattr__, __init__, announce, copy_file, copy_tree, debug_print, dump_options, ensure_dirname, ensure_filename, ensure_finalized, ensure_string, ensure_string_list, execute, get_command_name, get_finalized_command, get_sub_commands, make_archive, make_file, mkpath, move_file, reinitialize_command, run_command, set_undefined_options, spawn, warn

Inherited from distutils.cmd.Command (private): _ensure_stringlike, _ensure_tested_string

Class Variables [hide private]
  description = 'install qmtest extension classes.'

Inherited from distutils.command.install_lib.install_lib: boolean_options, negative_opt, user_options

Inherited from distutils.cmd.Command: sub_commands

Method Details [hide private]

finalize_options(self)

source code 

Set final values for all the options that this command supports. This is always called as late as possible, ie. after any option assignments from the command-line or from other commands have been done. Thus, this is the place to code option dependencies: if 'foo' depends on 'bar', then it is safe to set 'foo' from 'bar' as long as 'foo' still has the same value it was assigned in 'initialize_options()'.

This method must be implemented by all command classes.

Overrides: distutils.cmd.Command.finalize_options
(inherited documentation)

run(self)

source code 

A command's raison d'etre: carry out the action it exists to perform, controlled by the options initialized in 'initialize_options()', customized by other commands, the setup script, the command-line, and config files, and finalized in 'finalize_options()'. All terminal output and filesystem interaction should be done by 'run()'.

This method must be implemented by all command classes.

Overrides: distutils.cmd.Command.run
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.user-module.html0000664000076400007640000000612411122067144024323 0ustar stefanstefan user

Module user


Classes

AccountDisabledError
AuthenticationError
Authenticator
DefaultAuthenticator
DefaultDatabase
Group
User
XmlDatabase
XmlDatabaseAuthenticator
XmlDatabaseError

Functions

create_dom_for_group
create_dom_for_user
get_group_from_dom
get_user_from_dom
load_xml_database

Variables

authenticator
database
xml_user_database_dtd

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dg_test-pysrc.html0000664000076400007640000047320311122067153026506 0ustar stefanstefan qm.test.classes.dg_test
Package qm :: Package test :: Package classes :: Module dg_test
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.dg_test

  1  ######################################################################## 
  2  # 
  3  # File:   dg_test.py 
  4  # Author: Mark Mitchell 
  5  # Date:   04/17/2003 
  6  # 
  7  # Contents: 
  8  #   DGTest 
  9  # 
 10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  from   dejagnu_test import DejaGNUTest 
 21  import fnmatch 
 22  import os 
 23  from   qm.test.result import Result 
 24  from   qm.fields import BooleanField 
 25  import re 
 26   
 27  ######################################################################## 
 28  # Classes 
 29  ######################################################################## 
 30   
31 -class DGTest(DejaGNUTest):
32 """A 'DGTest' is a test using the DejaGNU 'dg' driver. 33 34 This test class emulates the 'dg.exp' source file in the DejaGNU 35 distribution.""" 36
37 - class DGException(Exception):
38 """The exception class raised by 'DGTest'. 39 40 When a 'DGTest' method detects an error situation, it raises 41 an exception of this type.""" 42 43 pass
44 45 46 47 __dg_command_regexp \ 48 = re.compile(r"{[ \t]+dg-([-a-z]+)[ \t]+(.*)[ \t]+}[^}]*$") 49 """A regular expression matching commands embedded in the source file.""" 50 51 # The values of these constants have been chosen so that they 52 # match the valid values for the 'dg-do' command. 53 KIND_PREPROCESS = "preprocess" 54 KIND_COMPILE = "compile" 55 KIND_ASSEMBLE = "assemble" 56 KIND_LINK = "link" 57 KIND_RUN = "run" 58 59 keep_output = BooleanField(default_value=False, 60 description="""True if the output file should be retained 61 after the test is complete. Otherwise, it is removed.""") 62 63 _default_kind = KIND_COMPILE 64 """The default test kind. 65 66 This value can be overridden by a 'dg-do' command in the test file.""" 67 68 __test_kinds = ( 69 KIND_PREPROCESS, 70 KIND_COMPILE, 71 KIND_ASSEMBLE, 72 KIND_LINK, 73 KIND_RUN 74 ) 75 """The kinds of tests supported by 'dg.exp'.""" 76 77 __DIAG_BOGUS = "bogus" 78 __DIAG_ERROR = "error" 79 __DIAG_WARNING = "warning" 80 81 __diagnostic_descriptions = { 82 __DIAG_ERROR : "errors", 83 __DIAG_WARNING : "warnings", 84 __DIAG_BOGUS : "bogus messages", 85 "build" : "build failure", 86 } 87 """A map from dg diagnostic kinds to descriptive strings.""" 88
89 - def _RunDGTest(self, tool_flags, default_options, context, result, 90 path = None, 91 default_kind = None, 92 keep_output = None):
93 """Run a 'dg' test. 94 95 'tool_flags' -- A list of strings giving a set of options to be 96 provided to the tool being tested. 97 98 'default_options' -- A list of strings giving a default set of 99 options to be provided to the tool being tested. These options 100 can be overridden by an embedded 'dg-options' command in the 101 test itself. 102 103 'context' -- The 'Context' in which this test is running. 104 105 'result' -- The 'Result' of the test execution. 106 107 'path' -- The path to the test file. If 'None', the main test 108 file path is used. 109 110 'default_kind' -- The kind of test to perform. If this value 111 is 'None', then 'self._default_kind' is used. 112 113 'keep_output' -- True if the output file should be retained 114 after the test is complete. Otherwise, it is removed. 115 116 This function emulates 'dg-test'.""" 117 118 # Intialize. 119 if default_kind is None: 120 default_kind = self._default_kind 121 self._kind = default_kind 122 self._selected = None 123 self._expectation = None 124 self._options = list(default_options) 125 self._diagnostics = [] 126 self._excess_errors_expected = False 127 self._final_commands = [] 128 # Iterate through the test looking for embedded commands. 129 line_num = 0 130 if not path: 131 path = self._GetSourcePath() 132 root = self.GetDatabase().GetRoot() 133 if path.startswith(root): 134 self._name = path[len(root) + 1:] 135 else: 136 # We prepend "./" for output compatibility with DejaGNU. 137 self._name = os.path.join(".", os.path.basename(path)) 138 for l in open(path).xreadlines(): 139 line_num += 1 140 m = self.__dg_command_regexp.search(l) 141 if m: 142 f = getattr(self, "_DG" + m.group(1).replace("-", "_")) 143 args = self._ParseTclWords(m.group(2), 144 { "srcdir" : root }) 145 f(line_num, args, context) 146 147 # If this test does not need to be run on this target, stop. 148 if self._selected == 0: 149 self._RecordDejaGNUOutcome(result, 150 self.UNSUPPORTED, 151 self._name) 152 return 153 154 # Run the tool being tested and process its output. 155 file = self._RunDGToolPortion(path, tool_flags, context, result) 156 157 # Run the executable generated (if applicable). 158 self._RunDGExecutePortion(file, context, result) 159 160 # Run dg-final tests. 161 for c, a in self._final_commands: 162 self._ExecuteFinalCommand(c, a, context, result) 163 164 # For backward compatibility the function parameter overrides 165 # the extension argument, if defined. 166 do_keep_output = keep_output is None and self.keep_output or keep_output 167 # Remove the output file. 168 if not do_keep_output: 169 try: 170 os.remove(file) 171 except: 172 pass
173
174 - def _RunDGToolPortion(self, path, tool_flags, context, result):
175 """Perform the tool-running portions of a DG test. 176 177 Calls '_RunTool' and processes its output. 178 179 returns -- The filename of the generated file.""" 180 181 # Run the tool being tested. 182 output, file = self._RunTool(path, self._kind, 183 tool_flags + self._options, 184 context, 185 result) 186 187 # Check to see if the right diagnostic messages appeared. 188 # This algorithm takes time proportional to the number of 189 # lines in the output times the number of expected 190 # diagnostics. One could do much better, but DejaGNU does 191 # not. 192 for l, k, x, p, c in self._diagnostics: 193 # Remove all occurrences of this diagnostic from the 194 # output. 195 if l is not None: 196 ldesc = "%d" % l 197 l = ":%s:" % ldesc 198 else: 199 ldesc = "" 200 l = ldesc 201 output, matched = re.subn(r"(?m)^.+" + l + r".*(" + p + r").*$", 202 "", output) 203 # Record an appropriate test outcome. 204 message = ("%s %s (test for %s, line %s)" 205 % (self._name, c, 206 self.__diagnostic_descriptions[k], ldesc)) 207 if matched: 208 if k == self.__DIAG_BOGUS: 209 outcome = self.FAIL 210 else: 211 outcome = self.PASS 212 else: 213 if k == self.__DIAG_BOGUS: 214 outcome = self.PASS 215 else: 216 outcome = self.FAIL 217 218 self._RecordDejaGNUOutcome(result, outcome, message, x) 219 220 # Remove tool-specific messages that can be safely ignored. 221 output = self._PruneOutput(output) 222 223 # Remove leading blank lines. 224 output = re.sub(r"^\n+", "", output) 225 # If there's any output left, the test fails. 226 message = self._name + " (test for excess errors)" 227 if self._excess_errors_expected: 228 expected = self.FAIL 229 else: 230 expected = self.PASS 231 if output != "": 232 self._RecordDejaGNUOutcome(result, self.FAIL, 233 message, expected) 234 result["DGTest.excess_errors"] = result.Quote(output) 235 else: 236 self._RecordDejaGNUOutcome(result, self.PASS, 237 message, expected) 238 239 return file
240 241
242 - def _RunDGExecutePortion(self, file, context, result):
243 """Perform the executable-running portions of a DG test. 244 245 If this is a "run" test, runs the executable generated by the 246 tool and checks its output.""" 247 248 # Run the generated program. 249 if self._kind == "run": 250 if not os.path.exists(file): 251 message = (self._name 252 + " compilation failed to produce executable") 253 self._RecordDejaGNUOutcome(result, self.WARNING, message) 254 else: 255 outcome = self._RunTargetExecutable(context, result, file) 256 # Add an annotation indicating what happened. 257 message = self._name + " execution test" 258 self._RecordDejaGNUOutcome(result, outcome, message, 259 self._expectation)
260 261
262 - def _ExecuteFinalCommand(self, command, args, context, result):
263 """Run a command specified with 'dg-final'. 264 265 'command' -- A string giving the name of the command. 266 267 'args' -- A list of strings giving the arguments (if any) to 268 that command. 269 270 'context' -- The 'Context' in which this test is running. 271 272 'result' -- The 'Result' of this test.""" 273 274 raise self.DGException, \ 275 'dg-final command \"%s\" is not implemented' % command
276 277
278 - def _PruneOutput(self, output):
279 """Remove unintersting messages from 'output'. 280 281 'output' -- A string giving the output from the tool being 282 tested. 283 284 returns -- A modified version of 'output'. This modified 285 version does not contain tool output messages that are 286 irrelevant for testing purposes.""" 287 288 raise NotImplementedError
289 290
291 - def _RunTool(self, path, kind, options, context, result):
292 """Run the tool being tested. 293 294 'path' -- The path to the test file. 295 296 'kind' -- The kind of test to perform. 297 298 'options' -- A list of strings giving command-line options to 299 provide to the tool. 300 301 'context' -- The 'Context' for the test execution. 302 303 'result' -- The QMTest 'Result' for the test. 304 305 returns -- A pair '(output, file)' where 'output' consists of 306 any messages produced by the compiler, and 'file' is the name 307 of the file produced by the compilation, if any.""" 308 309 raise NotImplementedError
310 311
312 - def _DGdo(self, line_num, args, context):
313 """Emulate the 'dg-do' command. 314 315 'line_num' -- The line number at which the command was found. 316 317 'args' -- The arguments to the command, as a list of 318 strings. 319 320 'context' -- The 'Context' in which the test is running.""" 321 322 if len(args) > 2: 323 self._Error("dg-do: too many arguments") 324 325 if len(args) >= 2: 326 code = self._ParseTargetSelector(args[1], context) 327 if code == "S": 328 self._selected = 1 329 elif code == "N": 330 if self._selected != 1: 331 self._selected = 0 332 elif code == "F": 333 self._expectation = Result.FAIL 334 else: 335 self._selected = 1 336 self._expectation = Result.PASS 337 338 kind = args[0] 339 if kind not in self.__test_kinds: 340 self._Error("dg-do: syntax error") 341 342 self._kind = kind
343 344
345 - def _DGfinal(self, line_num, args, context):
346 """Emulate the 'dg-final' command. 347 348 'line_num' -- The line number at which the command was found. 349 350 'args' -- The arguments to the command, as a list of 351 strings. 352 353 'context' -- The 'Context' in which the test is running.""" 354 355 if len(args) > 1: 356 self._Error("dg-final: too many arguments") 357 358 words = self._ParseTclWords(args[0]) 359 self._final_commands.append((words[0], words[1:]))
360 361
362 - def _DGoptions(self, line_num, args, context):
363 """Emulate the 'dg-options' command. 364 365 'line_num' -- The line number at which the command was found. 366 367 'args' -- The arguments to the command, as a list of 368 strings. 369 370 'context' -- The 'Context' in which the test is running.""" 371 372 if len(args) > 2: 373 self._Error("'dg-options': too many arguments") 374 375 if len(args) >= 2: 376 code = self._ParseTargetSelector(args[1], context) 377 if code == "S": 378 self._options = self._ParseTclWords(args[0]) 379 elif code != "N": 380 self._Error("'dg-options': 'xfail' not allowed here") 381 else: 382 self._options = self._ParseTclWords(args[0])
383 384
385 - def _DGbogus(self, line_num, args, context):
386 """Emulate the 'dg-bogus' command. 387 388 'line_num' -- The number at which the command was found. 389 390 'args' -- The arguments to the command, as a list of 391 strings. 392 393 'context' -- The 'Context' in which the test is running.""" 394 395 self.__ExpectDiagnostic(self.__DIAG_BOGUS, line_num, args, context)
396 397
398 - def _DGwarning(self, line_num, args, context):
399 """Emulate the 'dg-warning' command. 400 401 'line_num' -- The number at which the command was found. 402 403 'args' -- The arguments to the command, as a list of 404 strings. 405 406 'context' -- The 'Context' in which the test is running.""" 407 408 self.__ExpectDiagnostic(self.__DIAG_WARNING, line_num, args, context)
409 410
411 - def _DGerror(self, line_num, args, context):
412 """Emulate the 'dg-error' command. 413 414 'line_num' -- The number at which the command was found. 415 416 'args' -- The arguments to the command, as a list of 417 strings. 418 419 'context' -- The 'Context' in which the test is running.""" 420 421 self.__ExpectDiagnostic(self.__DIAG_ERROR, line_num, args, context)
422 423
424 - def _DGexcess_errors(self, line_num, args, context):
425 """Emulate the 'dg-excess-errors' command. 426 427 'line_num' -- The line number at which the command was found. 428 429 'args' -- The arguments to the command, as a list of 430 strings. 431 432 'context' -- The 'Context' in which the test is running.""" 433 434 if len(args) > 2: 435 self._Error("'dg-excess-errors': too many arguments") 436 437 if len(args) >= 2: 438 code = self._ParseTargetSelector(args[1], context) 439 if code in ("F", "S"): 440 self._excess_errors_expected = True 441 else: 442 self._excess_errors_expected = True
443 444
445 - def __ExpectDiagnostic(self, kind, line_num, args, context):
446 """Register an expected diagnostic. 447 448 'kind' -- The kind of diagnostic expected. 449 450 'line_num' -- The number at which the command was found. 451 452 'args' -- The arguments to the command, as a list of 453 strings. 454 455 'context' -- The 'Context' in which the test is running.""" 456 457 if len(args) > 4: 458 self._Error("'dg-" + kind + "': too many arguments") 459 460 if len(args) >= 4: 461 l = args[3] 462 if l == "0": 463 line_num = None 464 elif l != ".": 465 line_num = int(args[3]) 466 467 # Parse the target selector, if any. 468 expectation = self.PASS 469 if len(args) >= 3: 470 code = self._ParseTargetSelector(args[2], context) 471 if code == "N": 472 return 473 if code == "F": 474 expectation = self.FAIL 475 476 if len(args) >= 2: 477 comment = args[1] 478 else: 479 comment = "" 480 481 self._diagnostics.append((line_num, kind, expectation, 482 args[0], comment))
483 484
485 - def _ParseTargetSelector(self, selector, context):
486 """Parse the target 'selector'. 487 488 'selector' -- A target selector. 489 490 'context' -- The 'Context' in which the test is running. 491 492 returns -- For a 'target' selector, 'S' if this test should be 493 run, or 'N' if it should not. For an 'xfail' selector, 'F' if 494 the test is expected to fail; 'P' if if not. 495 496 This function emulates dg-process-target.""" 497 498 # Split the selector into words. In the DejaGNU code, this 499 # operation is accomplished by treating the string as Tcl 500 # list. 501 words = selector.split() 502 # Check the first word. 503 if words[0] != "target" and words[0] != "xfail": 504 raise QMException, "Invalid selector." 505 # The rest of the selector is a space-separate list of 506 # patterns. See if any of them are matched by the current 507 # target platform. 508 target = self._GetTarget(context) 509 match = 0 510 for p in words[1:]: 511 if (p == "native" and self._IsNative(context) 512 or fnmatch.fnmatch(target, p)): 513 match = 1 514 break 515 516 if words[0] == "target": 517 if match: 518 return "S" 519 else: 520 return "N" 521 else: 522 if match: 523 return "F" 524 else: 525 return "P"
526

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.trace-pysrc.html0000664000076400007640000007520011122067154023535 0ustar stefanstefan qm.trace
Package qm :: Module trace
[hide private]
[frames] | no frames]

Source Code for Module qm.trace

  1  ######################################################################## 
  2  # 
  3  # File:   trace.py 
  4  # Author: Mark Mitchell 
  5  # Date:   01/25/2002 
  6  # 
  7  # Contents: 
  8  #   Tracer 
  9  # 
 10  # Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import os 
 21  import sys 
 22   
 23  ######################################################################## 
 24  # Classes 
 25  ######################################################################## 
 26   
27 -class Tracer:
28 """A 'Tracer' outputs trace messages useful for debugging.""" 29 30 prefix = 'QM_THRESHOLD_' 31 """The prefix for an environment variable that indicates a 32 threshold for a particular trace category. The string following 33 the prefix gives the name of the trace category. If the 34 environment variable has no associated level, the associated level 35 is one. Otherwise, the associated level is given by the value of 36 the environment variable.""" 37
38 - def __init__(self, file=sys.stderr):
39 """Construct a new 'Tracer'. 40 41 'file' -- The file object to which output should be written.""" 42 43 self.__file = file 44 self.__thresholds = {} 45 46 # Take any environment variables that begin with QM_THRESHOLD_ 47 # as the initial values for thresholds. 48 keys = filter (lambda key: (key[:len(Tracer.prefix)] 49 == Tracer.prefix), 50 os.environ.keys()) 51 for key in keys: 52 level = os.environ[key] 53 if level: 54 level = int(level) 55 else: 56 level = 1 57 self.SetThreshold(key[len(Tracer.prefix):], level)
58 59
60 - def Write(self, message, category, level=0):
61 """Output a trace message. 62 63 'message' -- A string giving the contents of the message. The 64 message should begin with a capital letter and end with a 65 period. 66 67 'category' -- A string indicating the category to which this 68 message belongs. 69 70 'level' -- A non-negative integer indicating the level at 71 which the message should be output. 72 73 Every category has an associated threshold. If the level of 74 the 'message' is less than the threshold, the mesage will be 75 output.""" 76 77 if level < self.GetThreshold(category): 78 self.__file.write("[%s]: %s\n" % (category, message)) 79 self.__file.flush()
80 81
82 - def GetThreshold(self, category):
83 """Return the current threshold for 'category'. 84 85 'category' -- A string giving a trace category. 86 87 returns -- The threshold associated with 'category'. If no 88 threshold has been set, the threshold is considered to be 89 zero.""" 90 91 return self.__thresholds.get(category, 0)
92 93
94 - def SetThreshold(self, category, level):
95 """Set the threshold associated with 'category'. 96 97 'category' --A string giving a trace category. 98 99 'level' -- A non-negative integer indicating the threshold 100 level for 'category'.""" 101 102 self.__thresholds[category] = level
103

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.VSEval-pysrc.html0000664000076400007640000017114411122067154030675 0ustar stefanstefan qm.external.DocumentTemplate.VSEval
Package qm :: Package external :: Package DocumentTemplate :: Module VSEval
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.VSEval

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  """Very Safe Python Expressions 
 14  """ 
 15  __rcs_id__='$Id: VSEval.py 1069 2008-11-13 21:55:43Z stefan $' 
 16  __version__='$Revision: 1069 $'[11:-2] 
 17   
 18  from string import translate, strip 
 19  import string 
 20  gparse=None 
 21   
 22  nltosp=string.maketrans('\r\n','  ') 
 23   
24 -def default_slicer(env, s, *ind):
25 l=len(ind) 26 if l==2: return s[ind[0]:ind[1]] 27 elif l==1: return s[ind[0]:] 28 return s[:]
29
30 -def careful_mul(env, *factors):
31 # r = result (product of all factors) 32 # c = count (product of all non-sequence factors) 33 # s flags whether any of the factors is a sequence 34 r=c=1 35 s=None 36 for factor in factors: 37 try: 38 l=len(factor) 39 s=1 40 except TypeError: 41 c=c*factor 42 if s and c > 1000: 43 raise TypeError, \ 44 'Illegal sequence repeat (too many repetitions: %d)' % c 45 r=r*factor 46 return r
47 48 49 default_globals={ 50 '__builtins__':{}, 51 '__guarded_mul__': careful_mul, 52 '__guarded_getattr__': lambda env, inst, name: getattr(inst, name), 53 '__guarded_getitem__': lambda env, coll, key: coll[key], 54 '__guarded_getslice__': default_slicer, 55 } 56 57 58
59 -class Eval:
60 """Provide a very-safe environment for evaluating expressions 61 62 This class lets you overide operations, __power__, __mul__, 63 __div__, __mod__, __add__, __sub__, __getitem__, __lshift__, 64 __rshift__, __and__, __xor__, __or__,__pos__, __neg__, __not__, 65 __repr__, __invert__, and __getattr__. 66 67 For example, __mult__ might be overridden to prevent expressions like:: 68 69 'I like spam' * 100000000 70 71 or to disallow or limit attribute access. 72 73 """ 74
75 - def __init__(self, expr, globals=default_globals):
76 """Create a 'safe' expression 77 78 where: 79 80 expr -- a string containing the expression to be evaluated. 81 82 globals -- A global namespace. 83 """ 84 global gparse 85 if gparse is None: import gparse 86 87 expr=strip(expr) 88 89 self.__name__=expr 90 expr=translate(expr,nltosp) 91 self.expr=expr 92 self.globals=globals 93 94 co=compile(expr,'<string>','eval') 95 96 names=list(co.co_names) 97 98 # Check for valid names, disallowing names that begin with '_' or 99 # 'manage'. This is a DC specific rule and probably needs to be 100 # made customizable! 101 for name in names: 102 if name[:1]=='_' and name not in ('_', '_vars', '_getattr'): 103 raise TypeError, 'illegal name used in expression' 104 105 used={} 106 107 i=0 108 code=co.co_code 109 l=len(code) 110 LOAD_NAME=101 111 HAVE_ARGUMENT=90 112 def HAS_ARG(op): ((op) >= HAVE_ARGUMENT) 113 while(i < l): 114 c=ord(code[i]) 115 if c==LOAD_NAME: 116 name=names[ord(code[i+1])+256*ord(code[i+2])] 117 used[name]=1 118 i=i+3 119 elif c >= HAVE_ARGUMENT: i=i+3 120 else: i=i+1 121 122 self.code=gparse.compile(expr,'<string>','eval') 123 self.used=tuple(used.keys())
124
125 - def eval(self, mapping):
126 d={'_vars': mapping} 127 code=self.code 128 globals=self.globals 129 for name in self.used: 130 try: d[name]=mapping.getitem(name,0) 131 except KeyError: 132 if name=='_getattr': 133 d['__builtins__']=globals 134 exec compiled_getattr in d 135 136 return eval(code,globals,d)
137
138 - def __call__(self, **kw):
139 return eval(self.code, self.globals, kw)
140 141 compiled_getattr=compile( 142 'def _getattr(o,n): return __guarded_getattr__(_vars,o,n)', 143 '<string>','exec') 144

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Util-pysrc.html0000664000076400007640000056462411122067162031051 0ustar stefanstefan qm.external.DocumentTemplate.DT_Util
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Util
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_Util

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  """DTML Utilities 
 14   
 15  $Id: DT_Util.py 1069 2008-11-13 21:55:43Z stefan $""" 
 16   
 17  import re 
 18  import VSEval 
 19   
 20  str=__builtins__['str'] # Waaaaa, waaaaaaaa needed for pickling waaaaa 
 21   
 22  ParseError='Document Template Parse Error' 
 23  ValidationError='Unauthorized' 
 24   
 25   
26 -def html_quote(v, name='(Unknown name)', md={}, 27 character_entities=( 28 (('&'), '&amp;'), 29 (('<'), '&lt;' ), 30 (('>'), '&gt;' ), 31 (('"'), '&quot;'))): #"
32 text=str(v) 33 for re,name in character_entities: 34 if text.find(re) >= 0: text=text.split(re).join(name) 35 return text 36
37 -def int_param(params,md,name,default=0, st=type('')):
38 v = params.get(name, default) 39 if v: 40 try: 41 v = int(v) 42 except: 43 v = md[v] 44 if isinstance(v, str): 45 v = int(v) 46 return v or 0
47 48 _marker=[] 49
50 -def careful_getattr(md, inst, name, default=_marker):
51 52 if name[:1]!='_': 53 54 # Try to get the attribute normally so that we don't 55 # accidentally acquire when we shouldn't. 56 try: v=getattr(inst, name) 57 except: 58 if default is not _marker: 59 return default 60 raise 61 62 validate=md.validate 63 64 if validate is None: return v 65 66 if hasattr(inst,'aq_acquire'): 67 return inst.aq_acquire(name, validate, md) 68 69 if validate(inst,inst,name,v,md): return v 70 71 raise ValidationError, name
72
73 -def careful_hasattr(md, inst, name):
74 v=getattr(inst, name, _marker) 75 if v is not _marker: 76 try: 77 if name[:1]!='_': 78 validate=md.validate 79 if validate is None: return 1 80 81 if hasattr(inst,'aq_acquire'): 82 inst.aq_acquire(name, validate, md) 83 return 1 84 85 if validate(inst,inst,name,v,md): return 1 86 except: pass 87 return 0
88
89 -def careful_getitem(md, mapping, key):
90 v=mapping[key] 91 92 if type(v) is type(''): return v # Short-circuit common case 93 94 validate=md.validate 95 if validate is None or validate(mapping,mapping,None,v,md): return v 96 raise ValidationError, key
97
98 -def careful_getslice(md, seq, *indexes):
99 v=len(indexes) 100 if v==2: 101 v=seq[indexes[0]:indexes[1]] 102 elif v==1: 103 v=seq[indexes[0]:] 104 else: v=seq[:] 105 106 if type(seq) is type(''): return v # Short-circuit common case 107 108 validate=md.validate 109 if validate is not None: 110 for e in v: 111 if not validate(seq,seq,None,e,md): 112 raise ValidationError, 'unauthorized access to slice member' 113 114 return v
115
116 -def careful_range(md, iFirst, *args):
117 # limited range function from Martijn Pieters 118 RANGELIMIT = 1000 119 if not len(args): 120 iStart, iEnd, iStep = 0, iFirst, 1 121 elif len(args) == 1: 122 iStart, iEnd, iStep = iFirst, args[0], 1 123 elif len(args) == 2: 124 iStart, iEnd, iStep = iFirst, args[0], args[1] 125 else: 126 raise AttributeError, 'range() requires 1-3 int arguments' 127 if iStep == 0: raise ValueError, 'zero step for range()' 128 iLen = int((iEnd - iStart) / iStep) 129 if iLen < 0: iLen = 0 130 if iLen >= RANGELIMIT: raise ValueError, 'range() too large' 131 return range(iStart, iEnd, iStep)
132 133 import string, math, random 134 135 try: 136 import ExtensionClass 137 from cDocumentTemplate import InstanceDict, TemplateDict, render_blocks 138 except: from pDocumentTemplate import InstanceDict, TemplateDict, render_blocks 139 140 141 d=TemplateDict.__dict__ 142 for name in ('None', 'abs', 'chr', 'divmod', 'float', 'hash', 'hex', 'int', 143 'len', 'max', 'min', 'oct', 'ord', 'round', 'str'): 144 d[name]=__builtins__[name] 145 d['string']=string 146 d['math']=math 147 d['random']=random 148
149 -def careful_pow(self, x, y, z):
150 if not z: raise ValueError, 'pow(x, y, z) with z==0' 151 return pow(x,y,z)
152 153 d['pow']=careful_pow 154 155 try: 156 import random 157 d['random']=random 158 except: pass 159 160 try: 161 import DateTime 162 d['DateTime']=DateTime.DateTime 163 except: pass 164
165 -def test(self, *args):
166 l=len(args) 167 for i in range(1, l, 2): 168 if args[i-1]: return args[i] 169 170 if l%2: return args[-1]
171 172 d['test']=test 173
174 -def obsolete_attr(self, inst, name, md):
175 return careful_getattr(md, inst, name)
176 177 d['attr']=obsolete_attr 178 d['getattr']=careful_getattr 179 d['hasattr']=careful_hasattr 180 d['range']=careful_range 181 182 #class namespace_: 183 # __allow_access_to_unprotected_subobjects__=1 184
185 -def namespace(self, **kw):
186 """Create a tuple consisting of a single instance whose attributes are 187 provided as keyword arguments.""" 188 if getattr(self, '__class__', None) != TemplateDict: 189 raise TypeError,'''A call was made to DT_Util.namespace() with an 190 incorrect "self" argument. It could be caused by a product which 191 is not yet compatible with this version of Zope. The traceback 192 information may contain more details.)''' 193 return apply(self, (), kw)
194 195 d['namespace']=namespace 196
197 -def render(self, v):
198 "Render an object in the way done by the 'name' attribute" 199 if hasattr(v, '__render_with_namespace__'): 200 v = v.__render_with_namespace__(self) 201 else: 202 vbase = getattr(v, 'aq_base', v) 203 if callable(vbase): 204 if getattr(vbase, 'isDocTemp', 0): 205 v = v(None, self) 206 else: 207 v = v() 208 return v
209 210 d['render']=render 211 212 expr_globals={ 213 '__builtins__':{}, 214 '__guarded_mul__': VSEval.careful_mul, 215 '__guarded_getattr__': careful_getattr, 216 '__guarded_getitem__': careful_getitem, 217 '__guarded_getslice__': careful_getslice, 218 } 219
220 -class Eval(VSEval.Eval):
221
222 - def eval(self, mapping):
223 d={'_vars': mapping, '_': mapping} 224 code=self.code 225 globals=self.globals 226 for name in self.used: 227 __traceback_info__ = name 228 try: d[name]=mapping.getitem(name,0) 229 except KeyError: 230 if name=='_getattr': 231 d['__builtins__']=globals 232 exec compiled_getattr in d 233 234 return eval(code,globals,d)
235 236
237 -def name_param(params,tag='',expr=0, attr='name', default_unnamed=1):
238 used=params.has_key 239 __traceback_info__=params, tag, expr, attr 240 241 #if expr and used('expr') and used('') and not used(params['']): 242 # # Fix up something like: <!--#in expr="whatever" mapping--> 243 # params[params['']]=default_unnamed 244 # del params[''] 245 246 if used(''): 247 v=params[''] 248 249 if v[:1]=='"' and v[-1:]=='"' and len(v) > 1: # expr shorthand 250 if used(attr): 251 raise ParseError, ('%s and expr given' % attr, tag) 252 if expr: 253 if used('expr'): 254 raise ParseError, ('two exprs given', tag) 255 v=v[1:-1] 256 try: expr=Eval(v, expr_globals) 257 except SyntaxError, v: 258 raise ParseError, ( 259 '<strong>Expression (Python) Syntax error</strong>:' 260 '\n<pre>\n%s\n</pre>\n' % v[0], 261 tag) 262 return v, expr 263 else: raise ParseError, ( 264 'The "..." shorthand for expr was used in a tag ' 265 'that doesn\'t support expr attributes.', 266 tag) 267 268 else: # name shorthand 269 if used(attr): 270 raise ParseError, ('Two %s values were given' % attr, tag) 271 if expr: 272 if used('expr'): 273 # raise 'Waaaaaa', 'waaa' 274 raise ParseError, ('%s and expr given' % attr, tag) 275 return params[''],None 276 return params[''] 277 278 elif used(attr): 279 if expr: 280 if used('expr'): 281 raise ParseError, ('%s and expr given' % attr, tag) 282 return params[attr],None 283 return params[attr] 284 elif expr and used('expr'): 285 name=params['expr'] 286 expr=Eval(name, expr_globals) 287 return name, expr 288 289 raise ParseError, ('No %s given' % attr, tag)
290 291 Expr_doc=""" 292 293 294 Python expression support 295 296 Several document template tags, including 'var', 'in', 'if', 'else', 297 and 'elif' provide support for using Python expressions via an 298 'expr' tag attribute. 299 300 Expressions may be used where a simple variable value is 301 inadequate. For example, an expression might be used to test 302 whether a variable is greater than some amount:: 303 304 <!--#if expr="age > 18"--> 305 306 or to transform some basic data:: 307 308 <!--#var expr="phone[:3]"--> 309 310 Objects available in the document templates namespace may be used. 311 Subobjects of these objects may be used as well, although subobject 312 access is restricted by the optional validation method. 313 314 In addition, a special additional name, '_', is available. The '_' 315 variable provides access to the document template namespace as a 316 mapping object. This variable can be useful for accessing objects 317 in a document template namespace that have names that are not legal 318 Python variable names:: 319 320 <!--#var expr="_['sequence-number']*5"--> 321 322 This variable also has attributes that provide access to standard 323 utility objects. These attributes include: 324 325 - The objects: 'None', 'abs', 'chr', 'divmod', 'float', 'hash', 326 'hex', 'int', 'len', 'max', 'min', 'oct', 'ord', 'pow', 327 'round', and 'str' from the standard Python builtin module. 328 329 - Special security-aware versions of 'getattr' and 'hasattr', 330 331 - The Python 'string', 'math', and 'random' modules, and 332 333 - A special function, 'test', that supports if-then expressions. 334 The 'test' function accepts any number of arguments. If the 335 first argument is true, then the second argument is returned, 336 otherwise if the third argument is true, then the fourth 337 argument is returned, and so on. If there is an odd number of 338 arguments, then the last argument is returned in the case that 339 none of the tested arguments is true, otherwise None is 340 returned. 341 342 For example, to convert a value to lower case:: 343 344 <!--#var expr="_.string.lower(title)"--> 345 346 """ 347 348 ListType=type([])
349 -def parse_params(text, 350 result=None, 351 tag='', 352 unparmre=re.compile('([\000- ]*([^\000- ="]+))'), 353 qunparmre=re.compile('([\000- ]*("[^"]*"))'), 354 parmre=re.compile('([\000- ]*([^\000- ="]+)=([^\000- ="]+))'), 355 qparmre=re.compile('([\000- ]*([^\000- ="]+)="([^"]*)")'), 356 **parms):
357 358 """Parse tag parameters 359 360 The format of tag parameters consists of 1 or more parameter 361 specifications separated by whitespace. Each specification 362 consists of an unnamed and unquoted value, a valueless name, or a 363 name-value pair. A name-value pair consists of a name and a 364 quoted or unquoted value separated by an '='. 365 366 The input parameter, text, gives the text to be parsed. The 367 keyword parameters give valid parameter names and default values. 368 369 If a specification is not a name-value pair and it is not the 370 first specification and it is a 371 valid parameter name, then it is treated as a name-value pair with 372 a value as given in the keyword argument. Otherwise, if it is not 373 a name-value pair, it is treated as an unnamed value. 374 375 The data are parsed into a dictionary mapping names to values. 376 Unnamed values are mapped from the name '""'. Only one value may 377 be given for a name and there may be only one unnamed value. """ 378 379 result=result or {} 380 381 # HACK - we precalculate all matches. Maybe we don't need them 382 # all. This should be fixed for performance issues 383 384 mo_p = parmre.match(text) 385 mo_q = qparmre.match(text) 386 mo_unp = unparmre.match(text) 387 mo_unq = qunparmre.match(text) 388 389 if mo_p: 390 name=mo_p.group(2).lower() 391 value=mo_p.group(3) 392 l=len(mo_p.group(1)) 393 elif mo_q: 394 name=mo_q.group(2).lower() 395 value=mo_q.group(3) 396 l=len(mo_q.group(1)) 397 elif mo_unp: 398 name=mo_unp.group(2) 399 l=len(mo_unp.group(1)) 400 if result: 401 if parms.has_key(name): 402 if parms[name] is None: raise ParseError, ( 403 'Attribute %s requires a value' % name, tag) 404 405 result[name]=parms[name] 406 else: raise ParseError, ( 407 'Invalid attribute name, "%s"' % name, tag) 408 else: 409 result['']=name 410 return parse_params(text[l:],result,**parms) 411 elif mo_unq: 412 name=mo_unq.group(2) 413 l=len(mo_unq.group(1)) 414 if result: raise ParseError, ( 415 'Invalid attribute name, "%s"' % name, tag) 416 else: result['']=name 417 return parse_params(text[l:],result,**parms) 418 else: 419 if not text or not text.strip(): return result 420 raise ParseError, ('invalid parameter: "%s"' % text, tag) 421 422 if not parms.has_key(name): 423 raise ParseError, ( 424 'Invalid attribute name, "%s"' % name, tag) 425 426 if result.has_key(name): 427 p=parms[name] 428 if type(p) is not ListType or p: 429 raise ParseError, ( 430 'Duplicate values for attribute "%s"' % name, tag) 431 432 result[name]=value 433 434 text=text[l:].strip() 435 if text: return parse_params(text,result,**parms) 436 else: return result
437

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.file-module.html0000664000076400007640000001201611122067145026111 0ustar stefanstefan qm.test.classes.file
Package qm :: Package test :: Package classes :: Module file
[hide private]
[frames] | no frames]

Module file

source code

File-related test classes.

Classes [hide private]
  SubstitutionField
A rule for performing a text substitution.
  FileContentsTest
Check that the contents of a file match the expected value.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.setup-module.html0000664000076400007640000001722011122067145023722 0ustar stefanstefan qm.setup
Package qm :: Module setup
[hide private]
[frames] | no frames]

Module setup

source code

Functions [hide private]
 
find_packages_r(packages, dirname, names)
If 'dirname' is a QM package, add it to 'packages'.
source code
Variables [hide private]
  packages = []
Function Details [hide private]

find_packages_r(packages, dirname, names)

source code 

If 'dirname' is a QM package, add it to 'packages'.

'packages' -- A mutable sequence of package names.

'dirname' -- The (relative) path from the base of the QM package to the directory.

'names' -- A mutable sequence of file names indicating files (and directories) contained in the directory given by 'dirname'.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Raise-pysrc.html0000664000076400007640000007731411122067153031172 0ustar stefanstefan qm.external.DocumentTemplate.DT_Raise
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Raise
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_Raise

 1  ############################################################################## 
 2  # 
 3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
 4  # 
 5  # This software is subject to the provisions of the Zope Public License, 
 6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
 7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
 8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
10  # FOR A PARTICULAR PURPOSE 
11  # 
12  ############################################################################## 
13  '''Raising exceptions 
14   
15     Errors can be raised from DTML using the 'raise' tag. 
16   
17     For example:: 
18   
19      <!--#if expr="condition_that_tests_input"--> 
20         <!--#raise type="Input Error"--> 
21             The value you entered is not valid 
22         <!--#/raise--> 
23      <!--#/if--> 
24   
25  ''' 
26  __rcs_id__='$Id: DT_Raise.py 1069 2008-11-13 21:55:43Z stefan $' 
27  __version__='$Revision: 1069 $'[11:-2] 
28   
29  from DT_Util import parse_params, name_param, render_blocks, str 
30   
31 -class Raise:
32 blockContinuations=() 33 name='raise' 34 expr='' 35
36 - def __init__(self, blocks):
37 38 tname, args, section = blocks[0] 39 self.section=section.blocks 40 args=parse_params(args, type='', expr='') 41 self.__name__, self.expr = name_param(args, 'raise', 1, attr='type')
42
43 - def render(self,md):
44 expr=self.expr 45 if expr is None: 46 t=self.__name__ 47 if t[-5:]=='Error' and __builtins__.has_key(t): 48 t=__builtins__[t] 49 else: 50 try: t=expr.eval(md) 51 except: t='Invalid Error Type Expression' 52 53 try: v=render_blocks(self.section,md) 54 except: v='Invalid Error Value' 55 56 raise t, v
57 58 __call__=render
59

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-O.html0000664000076400007640000002320211122067144024302 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

O



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external-pysrc.html0000664000076400007640000002011511122067154024254 0ustar stefanstefan qm.external
Package qm :: Package external
[hide private]
[frames] | no frames]

Source Code for Package qm.external

 1  ######################################################################## 
 2  # 
 3  # File:   __init__.py 
 4  # Author: Nathaniel Smith 
 5  # Date:   2003-04-09 
 6  # 
 7  # Contents: 
 8  #   Empty file to make external packages importable. 
 9  # 
10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  # DocumentTemplate uses regex and regsub, which are obsolete.  Prevent 
17  # Python from warning about these modules. 
18  import warnings 
19  warnings.filterwarnings("ignore", 
20                          r".*(regex|regsub).*", 
21                          DeprecationWarning, 
22                          r".*(DocumentTemplate|regsub).*") 
23   
24  ######################################################################## 
25  # Local Variables: 
26  # mode: python 
27  # indent-tabs-mode: nil 
28  # fill-column: 72 
29  # End: 
30   

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.attachment-module.html0000664000076400007640000000371111122067144025474 0ustar stefanstefan attachment

Module attachment


Classes

Attachment
AttachmentStore
FileAttachmentStore
TemporaryAttachmentStore

Functions

from_dom_node
make_dom_node
make_temporary_location

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.queue-module.html0000664000076400007640000000170311122067144024467 0ustar stefanstefan queue

Module queue



[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.label-module.html0000664000076400007640000002056711122067145023651 0ustar stefanstefan qm.label
Package qm :: Module label
[hide private]
[frames] | no frames]

Module label

source code

Classes [hide private]
  Label
A 'Label' identifies an entity.
Functions [hide private]
 
thunk(label)
Sanitize and convert 'label' to a valid label.
source code
Variables [hide private]
  __thunk_regex = re.compile(r'[^a-z0-9_]')
Function Details [hide private]

thunk(label)

source code 

Sanitize and convert 'label' to a valid label.

Makes a best-effort attempt to keep 'label' recognizable during the conversion.

returns -- A valid label.


././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test.CompilationTest-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test.CompilationTest-class.htm0000664000076400007640000007706611122067147033352 0ustar stefanstefan qm.test.classes.compilation_test.CompilationTest
Package qm :: Package test :: Package classes :: Module compilation_test :: Class CompilationTest
[hide private]
[frames] | no frames]

Class CompilationTest

source code

         object --+                
                  |                
extension.Extension --+            
                      |            
      runnable.Runnable --+        
                          |        
                  test.Test --+    
                              |    
 compiler_test.CompilerBase --+    
                              |    
     compiler_test.CompilerTest --+
                                  |
                                 CompilationTest

A CompilationTest compiles and optionally runs an executable. CompilationTest allows simple cross-testing. To run the executable on anything other than localhost, specify a Host descriptor by means of the context variable 'CompilationTest.target'.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code
 
_GetCompiler(self, context)
The name of the compiler executable is taken from the context variable 'CompilationTest.compiler_path'.
source code
 
_GetCompilationSteps(self, context)
Return the compilation steps for this test.
source code
 
_IsExecutionRequired(self)
Returns true if the generated executable should be run.
source code
 
_GetTarget(self, context)
Returns a target for the executable to be run on.
source code
 
_CheckOutput(self, context, result, prefix, output, diagnostics)
Check that the 'output' contains appropriate diagnostics.
source code

Inherited from compiler_test.CompilerTest (private): _CheckExecutableOutput, _DiagnosticsToString, _GetAnnotationPrefix, _GetExecutableArguments, _GetLibraryDirectories, _IsDiagnosticExpected, _MustExecutableExitSuccessfully, _RunExecutable

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Inherited from compiler_test.CompilerBase (private): _GetDirectory, _GetObjectFileName, _MakeDirectory, _RemoveDirectory

Class Variables [hide private]
  options = SetField(TextField(description= """Test-specific opt...
  ldflags = SetField(TextField(description= """Test-specific lin...
  source_files = SetField(TextField(description= "Source files t...
  executable = TextField(description= "The name of the executabl...
  execute = BooleanField(default_value= True, description= "Whet...

Inherited from compiler_test.CompilerTest (private): _ignored_diagnostic_regexps

Inherited from test.Test: PREREQUISITES_FIELD_ID, arguments, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

Overrides: test.Test.Run
(inherited documentation)

_GetCompiler(self, context)

source code 

The name of the compiler executable is taken from the context variable 'CompilationTest.compiler_path'.

Overrides: compiler_test.CompilerTest._GetCompiler

_GetCompilationSteps(self, context)

source code 

Return the compilation steps for this test.

'context' -- The 'Context' in which this test is being executed.

returns -- A sequence of 'CompilationStep' objects.

Overrides: compiler_test.CompilerTest._GetCompilationSteps
(inherited documentation)

_IsExecutionRequired(self)

source code 

Returns true if the generated executable should be run.

returns -- True if the generated executable should be run.

Overrides: compiler_test.CompilerTest._IsExecutionRequired
(inherited documentation)

_GetTarget(self, context)

source code 

Returns a target for the executable to be run on.

'context' -- The Context in which this test is being executed.

returns -- A Host to run the executable on.

Overrides: compiler_test.CompilerTest._GetTarget
(inherited documentation)

_CheckOutput(self, context, result, prefix, output, diagnostics)

source code 

Check that the 'output' contains appropriate diagnostics.

'context' -- The 'Context' for the test that is being executed.

'result' -- The 'Result' of the test.

'prefix' -- A string giving the prefix for any annotations to be added to the 'result'.

'output' -- A string giving the output of the compiler.

'diagnostics' -- The diagnostics that are expected for the compilation.

returns -- True if there were no errors so severe as to prevent execution of the test.

Overrides: compiler_test.CompilerTest._CheckOutput
(inherited documentation)

Class Variable Details [hide private]

options

Value:
SetField(TextField(description= """Test-specific options to pass to th\
e compiler."""))

ldflags

Value:
SetField(TextField(description= """Test-specific link flags to pass to\
 the compiler."""))

source_files

Value:
SetField(TextField(description= "Source files to be compiled."))

executable

Value:
TextField(description= "The name of the executable to be compiled.")

execute

Value:
BooleanField(default_value= True, description= "Whether or not to run \
the compiled executable.")

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.runnable-module.html0000664000076400007640000000210611122067144026125 0ustar stefanstefan runnable

Module runnable


Classes

Runnable

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.common-pysrc.html0000664000076400007640000101420211122067161023721 0ustar stefanstefan qm.common
Package qm :: Module common
[hide private]
[frames] | no frames]

Source Code for Module qm.common

  1  ######################################################################## 
  2  # 
  3  # File:   common.py 
  4  # Author: Alex Samuel 
  5  # Date:   2000-12-20 
  6  # 
  7  # Contents: 
  8  #   General-purpose classes and functions. 
  9  # 
 10  # Copyright (c) 2000, 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  from   calendar import timegm 
 21  import ConfigParser 
 22  import imp 
 23  import lock 
 24  import os 
 25  import os.path 
 26  import qm 
 27  import re 
 28  import string 
 29  import sys 
 30  import tempfile 
 31  import time 
 32  import traceback 
 33  import types 
 34  import getpass 
 35  import StringIO 
 36  import htmllib 
 37  import formatter 
 38  if sys.platform != "win32": 
 39      import fcntl 
 40       
 41  ######################################################################## 
 42  # program name 
 43  ######################################################################## 
 44   
 45  program_name = None 
 46  """The name of the application program.""" 
 47   
 48  ######################################################################## 
 49  # exceptions 
 50  ######################################################################## 
 51   
52 -class QMException(Exception):
53 """An exception generated directly by QM. 54 55 All exceptions thrown by QM should be derived from this class.""" 56
57 - def __init__(self, message):
58 """Construct a new 'QMException'. 59 60 'message' -- A string describing the cause of the message as 61 structured text. If this exception is not handled, the 62 'message' will be displayed as an error message.""" 63 64 Exception.__init__(self, message)
65 66 67
68 -class UserError(QMException):
69 70 pass
71 72 73
74 -class PythonException(QMException):
75 """A 'PythonException' is a wrapper around a Python exception. 76 77 A 'PythonException' is a 'QMException' and, as such, can be 78 processed by the QM error-handling routines. However, the raw 79 Python exception which triggered this exception can be obtained by 80 using the 'exc_type' and 'exc_value' attributes of this 81 exception.""" 82
83 - def __init__(self, message, exc_type, exc_value):
84 """Construct a new 'PythonException'. 85 86 'message' -- A string describing the cause of the message as 87 structured text. If this exception is not handled, the 88 'message' will be displayed as an error message. 89 90 'exc_type' -- The type of the Python exception. 91 92 'exc_value' -- The value of the Python exception.""" 93 94 QMException.__init__(self, message) 95 96 self.exc_type = exc_type 97 self.exc_value = exc_value
98 99 ######################################################################## 100 # classes 101 ######################################################################## 102
103 -class RcConfiguration(ConfigParser.ConfigParser):
104 """Interface object to QM configuration files. 105 106 Configuration files are in the format parsed by the standard 107 'ConfigParser' module, namely 'win.ini'--style files.""" 108 109 user_rc_file_name = ".qmrc" 110 """The name of the user configuration file.""" 111 112
113 - def __init__(self):
114 """Create a new configuration instance.""" 115 116 ConfigParser.ConfigParser.__init__(self) 117 if os.environ.has_key("HOME"): 118 home_directory = os.environ["HOME"] 119 rc_file = os.path.join(home_directory, self.user_rc_file_name) 120 # Note that it's OK to call 'read' even if the file doesn't 121 # exist. In that, case the parser simply will not 122 # accumulate any data. 123 self.read(rc_file)
124 125
126 - def Load(self, section):
127 """Load configuration. 128 129 'section' -- The configuration section from which subsequent 130 variables are loaded.""" 131 132 self.__section = section
133 134
135 - def Get(self, option, default, section=None):
136 """Retrieve a configuration variable. 137 138 'option' -- The name of the option to retrieve. 139 140 'default' -- The default value to return if the option is not 141 found. 142 143 'section' -- The section from which to retrieve the option. 144 'None' indicates the section specified to the 'Load' method for 145 this instance. 146 147 precondition -- The RC configuration must be loaded.""" 148 149 # Use the previously-specified default section, if one wasn't 150 # specified explicitly. 151 if section is None: 152 section = self.__section 153 154 try: 155 # Try to get the requested option. 156 return self.get(section, option) 157 except ConfigParser.NoSectionError: 158 # Couldn't find the section. 159 return default 160 except ConfigParser.NoOptionError: 161 # Couldn't find the option. 162 return default
163 164
165 - def GetOptions(self, section=None):
166 """Return a sequence of options. 167 168 'section' -- The section for which to list options, or 'None' 169 for the section specified to 'Load'. 170 171 precondition -- The RC configuration must be loaded.""" 172 173 # Use the previously-specified default section, if one wasn't 174 # specified explicitly. 175 if section is None: 176 section = self.__section 177 try: 178 options = self.options(section) 179 except ConfigParser.NoSectionError: 180 # Couldn't find the section. 181 return [] 182 else: 183 # 'ConfigParser' puts in a magic option '__name__', which is 184 # the name of the section. Remove it. 185 if "__name__" in options: 186 options.remove("__name__") 187 return options
188 189 190 ######################################################################## 191 # Functions 192 ######################################################################## 193
194 -def get_lib_directory(*components):
195 """Return the path to a file in the QM library directory.""" 196 197 # This is a file in the top-level QM library directory, so we can 198 # just return a path relative to ourselves. 199 return os.path.join(os.path.dirname(__file__), *components)
200 201
202 -def get_share_directory(*components):
203 """Return the path to a file in the QM data file directory.""" 204 205 return os.path.join(qm.prefix, qm.data_dir, *components)
206 207
208 -def get_doc_directory(*components):
209 """Return a path to a file in the QM documentation file directory.""" 210 211 return os.path.join(qm.prefix, qm.doc_dir, *components)
212 213
214 -def format_exception(exc_info):
215 """Format an exception as structured text. 216 217 'exc_info' -- A three-element tuple containing exception info, of 218 the form '(type, value, traceback)'. 219 220 returns -- A string containing a the formatted exception.""" 221 222 # Break up the exection info tuple. 223 type, value, trace = exc_info 224 # Generate output. 225 traceback_listing = format_traceback(exc_info) 226 return "Exception '%s' : '%s'\n\n%s\n" % (type, value, traceback_listing)
227 228
229 -def format_traceback(exc_info):
230 """Format an exception traceback as structured text. 231 232 'exc_info' -- A three-element tuple containing exception info, of 233 the form '(type, value, traceback)'. 234 235 returns -- A string containing a the formatted traceback.""" 236 237 return string.join(traceback.format_tb(exc_info[2]), "\n")
238 239
240 -def convert_from_dos_text(text):
241 """Replace CRLF with LF in 'text'.""" 242 243 return string.replace(text, "\r\n", "\n")
244 245 246 __load_module_lock = lock.RLock() 247 """A lock used by load_module.""" 248
249 -def load_module(name, search_path=sys.path, load_path=sys.path):
250 """Load a Python module. 251 252 'name' -- The fully-qualified name of the module to load, for 253 instance 'package.subpackage.module'. 254 255 'search_path' -- A sequence of directories. These directories are 256 searched to find the module. 257 258 'load_path' -- The setting of 'sys.path' when the module is loaded. 259 260 returns -- A module object. 261 262 raises -- 'ImportError' if the module cannot be found.""" 263 264 # The implementation of this function follows the prescription in 265 # the documentation for the standard Python 'imp' module. See also 266 # the 'knee' package included unofficially in the standard Python 267 # library. 268 269 # In order to avoid getting incomplete modules, grab a lock here. 270 # Use a recursive lock so that deadlock does not occur if the loaded 271 # module loads more modules. 272 __load_module_lock.acquire() 273 try: 274 # Is the module already loaded? 275 module = sys.modules.get(name) 276 if module: 277 return module 278 279 # The module may be in a package. Split the module path into 280 # components. 281 components = string.split(name, ".") 282 if len(components) > 1: 283 # The module is in a package. Construct the name of the 284 # containing package. 285 parent_package = string.join(components[:-1], ".") 286 # Load the containing package. 287 package = load_module(parent_package, search_path, load_path) 288 # Look for the module in the parent package. 289 search_path = package.__path__ 290 else: 291 # No containing package. 292 package = None 293 # The name of the module itself is the last component of the module 294 # path. 295 module_name = components[-1] 296 # Locate the module. 297 file, file_name, description = imp.find_module(module_name, 298 search_path) 299 # Find the module. 300 try: 301 # While loading the module, add 'path' to Python's module path, 302 # so that if the module references other modules, e.g. in the 303 # same directory, Python can find them. But remember the old 304 # path so we can restore it afterwards. 305 old_python_path = sys.path[:] 306 sys.path = load_path + sys.path 307 # Load the module. 308 try: 309 module = imp.load_module(name, file, file_name, description) 310 except: 311 # Don't leave a broken module object in sys.modules. 312 if sys.modules.has_key(name): 313 del sys.modules[name] 314 raise 315 # Restore the old path. 316 sys.path = old_python_path 317 # Loaded successfully. If it's contained in a package, put it 318 # into that package's name space. 319 if package is not None: 320 setattr(package, module_name, module) 321 return module 322 finally: 323 # Close the module file, if one was opened. 324 if file is not None: 325 file.close() 326 finally: 327 # Release the lock. 328 __load_module_lock.release()
329 330
331 -def load_class(name, search_path = sys.path, load_path = sys.path):
332 """Load a Python class. 333 334 'name' -- The fully-qualified (including package and module names) 335 class name, for instance 'package.subpackage.module.MyClass'. The 336 class must be at the top level of the module's namespace, i.e. not 337 nested in another class. 338 339 'search_path' -- A sequence of directories. These directories are 340 searched to find the module. 341 342 'load_path' -- The setting of 'sys.path' when the module is loaded. 343 344 returns -- A class object. 345 346 raises -- 'ImportError' if the module containing the class can't be 347 imported, or if there is no class with the specified name in that 348 module, or if 'name' doesn't correspond to a class.""" 349 350 # Make sure the class name is fully-qualified. It must at least be 351 # in a top-level module, so there should be at least one module path 352 # separator. 353 if not "." in name: 354 raise QMException, \ 355 "%s is not a fully-qualified class name" % name 356 # Split the module path into components. 357 components = string.split(name, ".") 358 # Reconstruct the full path to the containing module. 359 module_name = string.join(components[:-1], ".") 360 # The last element is the name of the class. 361 class_name = components[-1] 362 # Load the containing module. 363 module = load_module(module_name, search_path, load_path) 364 # Extract the requested class. 365 try: 366 klass = module.__dict__[class_name] 367 # Check to see the KLASS really is a class. Python 2.2's 368 # "new-style" classes are not instances of types.ClassType so we 369 # must check two conditions: one for old-style and one for 370 # new-style classes. 371 if (not isinstance(klass, types.ClassType) 372 and not issubclass(klass, object)): 373 # There's something by that name, but it's not a class 374 raise QMException, "%s is not a class" % name 375 return klass 376 except KeyError: 377 # There's no class with the requested name. 378 raise QMException, \ 379 "no class named %s in module %s" % (class_name, module_name)
380 381
382 -def split_path_fully(path):
383 """Split 'path' into components. 384 385 Uses 'os.path.split' recursively on the directory components of 386 'path' to separate all path components. 387 388 'path' -- The path to split. 389 390 returns -- A list of path componets.""" 391 392 dir, entry = os.path.split(path) 393 if dir == "" or dir == os.sep: 394 return [ entry ] 395 else: 396 return split_path_fully(dir) + [ entry ]
397 398
399 -def open_temporary_file_fd(suffix = ""):
400 """Create and open a temporary file. 401 402 'suffix' -- The last part of the temporary file name, as for 403 Python's 'mktemp' function. 404 405 The file is open for reading and writing. The caller is responsible 406 for deleting the file when finished with it. 407 408 returns -- A pair '(file_name, file_descriptor)' for the temporary 409 file.""" 410 411 file_name = tempfile.mktemp(suffix) 412 413 try: 414 # Attempt to open the file. 415 fd = os.open(file_name, 416 os.O_CREAT | os.O_EXCL | os.O_RDWR, 417 0600) 418 except: 419 exc_info = sys.exc_info() 420 raise QMException, \ 421 qm.error("temp file error", 422 file_name=file_name, 423 exc_class=str(exc_info[0]), 424 exc_arg=str(exc_info[1])) 425 return (file_name, fd)
426 427
428 -def open_temporary_file(mode = "w+b", suffix = ""):
429 """Create and open a temporary file. 430 431 'mode' -- The mode argument to pass to 'fopen'. 432 433 'suffix' -- The last part of the temporary file name, as for 434 Python's 'mktemp' function. 435 436 Like 'open_temporary_file_fd', except that the second element of the 437 return value is a file object.""" 438 439 # This function can just use NamedTemporaryFile when QMTest requires 440 # Python 2.3. 441 file_name, fd = open_temporary_file_fd(suffix) 442 return (file_name, os.fdopen(fd, mode))
443 444
445 -def close_file_on_exec(fd):
446 """Prevent 'fd' from being inherited across 'exec'. 447 448 'fd' -- A file descriptor, or object providing a 'fileno()' 449 method. 450 451 This function has no effect on Windows.""" 452 453 if sys.platform != "win32": 454 flags = fcntl.fcntl(fd, fcntl.F_GETFD) 455 try: 456 flags |= fcntl.FD_CLOEXEC 457 except AttributeError: 458 # The Python 2.2 RPM shipped with Red Hat Linux 7.3 does 459 # not define FD_CLOEXEC. Fortunately, FD_CLOEXEC is 1 on 460 # every UNIX system. 461 flags |= 1 462 fcntl.fcntl(fd, fcntl.F_SETFD, flags)
463 464
465 -def copy(object):
466 """Make a best-effort attempt to copy 'object'. 467 468 returns -- A copy of 'object', if feasible, or otherwise 469 'object'.""" 470 471 if type(object) is types.ListType: 472 # Copy lists. 473 return object[:] 474 elif type(object) is types.DictionaryType: 475 # Copy dictionaries. 476 return object.copy() 477 elif type(object) is types.InstanceType: 478 # For objects, look for a method named 'copy'. If there is one, 479 # call it. Otherwise, just return the object. 480 copy_function = getattr(object, "copy", None) 481 if callable(copy_function): 482 return object.copy() 483 else: 484 return object 485 else: 486 # Give up. 487 return object
488 489
490 -def wrap_lines(text, columns=72, break_delimiter="\\", indent=""):
491 """Wrap lines in 'text' to 'columns' columns. 492 493 'text' -- The text to wrap. 494 495 'columns' -- The maximum number of columns of text. 496 497 'break_delimiter' -- Text to place at the end of each broken line 498 (may be an empty string). 499 500 'indent' -- Text to place at the start of each line. The length of 501 'indent' does not count towards 'columns'. 502 503 returns -- The wrapped text.""" 504 505 # Break into lines. 506 lines = string.split(text, "\n") 507 # The length into which to break lines, leaving room for the 508 # delimiter. 509 new_length = columns - len(break_delimiter) 510 # Loop over lines. 511 for index in range(0, len(lines)): 512 line = lines[index] 513 # Too long? 514 if len(line) > columns: 515 # Yes. How many times will we have to break it? 516 breaks = len(line) / new_length 517 new_line = "" 518 # Construct the new line, disassembling the old as we go. 519 while breaks > 0: 520 new_line = new_line \ 521 + line[:new_length] \ 522 + break_delimiter \ 523 + "\n" + indent 524 line = line[new_length:] 525 breaks = breaks - 1 526 new_line = new_line + line 527 # Replace the old line with the new. 528 lines[index] = new_line 529 # Indent each line. 530 lines = map(lambda l, i=indent: i + l, lines) 531 # Rejoin lines. 532 return string.join(lines, "\n")
533 534
535 -def format_time(time_secs, local_time_zone=1):
536 """Generate a text format representing a date and time. 537 538 The output is in the format "YYYY-MM-DD HH:MM ZZZ". 539 540 'time_secs' -- The number of seconds since the start of the UNIX 541 epoch, UTC. 542 543 'local_time_zone' -- If true, format the time in the local time 544 zone. Otherwise, format it as UTC.""" 545 546 # Convert the time in seconds to a Python time 9-tuple. 547 if local_time_zone: 548 time_tuple = time.localtime(time_secs) 549 time_zone = time.tzname[time_tuple[8]] 550 else: 551 time_tuple = time.gmtime(time_secs) 552 time_zone = "UTC" 553 # Unpack the tuple. 554 year, month, day, hour, minute, second, weekday, julian_day, \ 555 dst_flag = time_tuple 556 # Generate the format. 557 return "%(year)4d-%(month)02d-%(day)02d " \ 558 "%(hour)02d:%(minute)02d %(time_zone)s" % locals()
559 560
561 -def format_time_iso(time_secs=None):
562 """Generate a ISO8601-compliant formatted date and time. 563 564 The output is in the format "YYYY-MM-DDThh:mm:ss+TZ", where TZ is 565 a timezone specifier. We always normalize to UTC (and hence 566 always use the special timezone specifier "Z"), to get proper 567 sorting behaviour. 568 569 'time_secs' -- The time to be formatted, as returned by 570 e.g. 'time.time()'. If 'None' (the default), uses the current 571 time. 572 573 returns -- The formatted time as a string.""" 574 575 if time_secs is None: 576 time_secs = time.time() 577 return time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime(time_secs))
578 579
580 -def parse_time_iso(time_string):
581 """Parse a ISO8601-compliant formatted date and time. 582 583 See also 'format_time_iso'. 584 585 'time_string' -- The string to be parsed, as returned by 586 e.g. 'format_time_iso'. 587 588 returns -- The time as a float, like that returned by 589 'time.time'.""" 590 591 return time.mktime(time.strptime(time_string, "%Y-%m-%dT%H:%M:%SZ"))
592 593
594 -def make_unique_tag():
595 """Return a unique tag string.""" 596 597 global _unique_tag 598 599 tag = "%d_%d" % (_unique_tag, os.getpid()) 600 _unique_tag = _unique_tag + 1 601 return tag
602 603
604 -def split_argument_list(command):
605 """Split a command into an argument list. 606 607 'command' -- A string containing a shell or similar command. 608 609 returns -- An argument list obtained by splitting the command.""" 610 611 # Strip leading and trailing whitespace. 612 command = string.strip(command) 613 # Split the command into argument list elements at spaces. 614 argument_list = re.split(" +", command) 615 return argument_list
616 617
618 -def parse_boolean(value):
619 """Parse a boolean string. 620 621 'value' -- A string. 622 623 returns -- True if 'value' is a true string, false if 'value' is a 624 false string. 625 626 raises -- 'ValueError' if 'value' is neither a true string, nor a 627 false string.""" 628 629 value = value.lower() 630 if value in ("1", "true", "yes", "on"): 631 return 1 632 elif value in ("0", "false", "no", "off"): 633 return 0 634 else: 635 raise ValueError, value
636 637
638 -def parse_string_list(value):
639 """Parse a string list. 640 641 'value' -- A string. 642 643 returns -- A list of strings. 644 645 raises -- 'ValueError' if 'value' contains unbalanced quotes.""" 646 647 # If the string doesn't contain quotes, simply split it. 648 if "'" not in value and '"' not in value: 649 return value.split() 650 # Else split it manually at non-quoted whitespace only. 651 breaks = [] 652 esc = False 653 quoted_1 = False # in '' quotes 654 quoted_2 = False # in "" quotes 655 value.strip() 656 # Find all non-quoted space. 657 for i, c in enumerate(value): 658 if c == '\\': 659 esc = not esc 660 continue 661 elif c == "'": 662 if not esc and not quoted_2: 663 quoted_1 = not quoted_1 664 elif c == '"': 665 if not esc and not quoted_1: 666 quoted_2 = not quoted_2 667 elif c in [' ', '\t']: 668 # This is a breakpoint if it is neither quoted nor escaped. 669 if not (quoted_1 or quoted_2 or esc): 670 breaks.append(i) 671 esc = False 672 # Make sure quotes are matched. 673 if quoted_1 or quoted_2 or esc: 674 raise ValueError, value 675 string_list = [] 676 start = 0 677 for end in breaks: 678 string_list.append(value[start:end]) 679 start = end 680 string_list.append(value[start:]) 681 return [s.strip() for s in string_list if s not in [' ', '\t']]
682 683 684 # No 'time.strptime' on non-UNIX systems, so use this instead. This 685 # version is more forgiving, anyway, and uses our standardized timestamp 686 # format. 687
688 -def parse_time(time_string, default_local_time_zone=1):
689 """Parse a date and/or time string. 690 691 'time_string' -- A string representing a date and time in the format 692 returned by 'format_time'. This function makes a best-effort 693 attempt to parse incomplete strings as well. 694 695 'default_local_time_zone' -- If the time zone is not specified in 696 'time_string' and this parameter is true, assume the time is in the 697 local time zone. If this parameter is false, assume the time is 698 UTC. 699 700 returns -- An integer number of seconds since the start of the UNIX 701 epoch, UTC. 702 703 Only UTC and the current local time zone may be specified explicitly 704 in 'time_string'.""" 705 706 # Sanitize. 707 time_string = string.strip(time_string) 708 time_string = re.sub(" +", " ", time_string) 709 time_string = re.sub("/", "-", time_string) 710 # On Windows, "UTC" is spelled "GMT Standard Time". Change that 711 # to "UTC" so that we can process it with the same code we use 712 # for UNIX. 713 time_string = re.sub("GMT Standard Time", "UTC", time_string) 714 # Break it apart. 715 components = string.split(time_string, " ") 716 717 # Do we have a time zone at the end? 718 if components[-1] == "UTC": 719 # It's explicitly UTC. 720 utc = 1 721 dst = 0 722 components.pop() 723 elif components[-1] == time.tzname[0]: 724 # It's explicitly our local non-DST time zone. 725 utc = 0 726 dst = 0 727 components.pop() 728 elif time.daylight and components[-1] == time.tzname[1]: 729 # It's explicitly our local DST time zone. 730 utc = 0 731 dst = 1 732 components.pop() 733 else: 734 # No explicit time zone. Use the specified default. 735 if default_local_time_zone: 736 utc = 0 737 dst = -1 738 else: 739 utc = 1 740 dst = 0 741 742 # Start with the current time, in the appropriate format. 743 if utc: 744 time_tuple = time.gmtime(time.time()) 745 else: 746 time_tuple = time.localtime(time.time()) 747 # Unpack the date tuple. 748 year, month, day = time_tuple[:3] 749 # Assume midnight. 750 hour = 0 751 minute = 0 752 753 # Look at each part of the date/time. 754 for component in components: 755 if string.count(component, "-") == 2: 756 # Looks like a date. 757 year, month, day = map(int, string.split(component, "-")) 758 elif string.count(component, ":") in [1, 2]: 759 # Looks like a time. 760 hour, minute = map(int, string.split(component, ":")[:2]) 761 else: 762 # Don't understand it. 763 raise ValueError 764 765 # Construct a Python time tuple. 766 time_tuple = (year, month, day, hour, minute, 0, 0, 0, dst) 767 # Convert it to seconds. 768 if utc: 769 return int(timegm(time_tuple)) 770 else: 771 return int(time.mktime(time_tuple))
772 773
774 -def parse_assignment(assignment):
775 """Parse an 'assignment' of the form 'name=value'. 776 777 'aassignment' -- A string. The string should have the form 778 'name=value'. 779 780 returns -- A pair '(name, value)'.""" 781 782 # Parse the assignment. 783 try: 784 (name, value) = string.split(assignment, "=", 1) 785 return (name, value) 786 except: 787 raise QMException, \ 788 qm.error("invalid keyword assignment", 789 argument=assignment)
790 791
792 -def read_assignments(file):
793 """Read assignments from a 'file'. 794 795 'file' -- A file object containing the context. When the file is 796 read, leading and trailing whitespace is discarded from each line 797 in the file. Then, lines that begin with a '#' and lines that 798 contain no characters are discarded. All other lines must be of 799 the form 'NAME=VALUE' and indicate an assignment to the context 800 variable 'NAME' of the indicated 'VALUE'. 801 802 returns -- A dictionary mapping each of the indicated 'NAME's to its 803 corresponding 'VALUE'. If multiple assignments to the same 'NAME' 804 are present, only the 'VALUE' from the last assignment is stored.""" 805 806 # Create an empty dictionary. 807 assignments = {} 808 809 # Read all the lines in the file. 810 lines = file.readlines() 811 # Strip out leading and trailing whitespace. 812 lines = map(string.strip, lines) 813 # Drop any lines that are completely blank or lines that are 814 # comments. 815 lines = filter(lambda x: x != "" and not x.startswith("#"), 816 lines) 817 # Go through each of the lines to process the context assignment. 818 for line in lines: 819 # Parse the assignment. 820 (name, value) = parse_assignment(line) 821 # Add it to the context. 822 assignments[name] = value 823 824 return assignments
825 826
827 -def get_username():
828 """Returns the current username as a string. 829 830 This is our best guess as to the username of the user who is 831 actually logged in, as opposed to the effective user id used for 832 running tests. 833 834 If the username cannot be found, raises a 'QMException'.""" 835 836 # First try using the 'getpass' module. 837 try: 838 return getpass.getuser() 839 except: 840 pass 841 842 # 'getpass' doesn't necessarily work on Windows, so if that fails, 843 # try the win32 function. 844 try: 845 import win32api 846 except ImportError: 847 pass 848 else: 849 try: 850 return win32api.GetUserName() 851 except: 852 raise PythonException("Error accessing win32 user database", 853 *sys.exc_info()[:2]) 854 855 # And if none of that worked, give up. 856 raise QMException, "Cannot determine user name."
857 858
859 -def get_userid():
860 """Returns the current user id as an integer. 861 862 This is the real user id, not the effective user id, to better track 863 who is actually running the tests. 864 865 If the user id cannot be found or is not defined, raises a 866 'QMException'.""" 867 868 try: 869 uid = os.getuid() 870 except AttributeError: 871 raise QMException, "User ids not supported on this system." 872 return uid
873 874
875 -def html_to_text(html, width=72):
876 """Renders HTML to text in a simple way. 877 878 'html' -- A string containing the HTML code to be rendered. 879 880 'width' -- Column at which to word-wrap. Default 72. 881 882 returns -- A string containing a plain text rendering of the 883 HTML.""" 884 885 s = StringIO.StringIO() 886 w = formatter.DumbWriter(s, width) 887 f = formatter.AbstractFormatter(w) 888 p = htmllib.HTMLParser(f) 889 p.feed(html) 890 p.close() 891 return s.getvalue()
892 893 894 ######################################################################## 895 # variables 896 ######################################################################## 897 898 rc = RcConfiguration() 899 """The configuration stored in system and user rc files.""" 900 901 # The next number to be used when handing out unqiue tag strings. 902 _unique_tag = 0 903 904 ######################################################################## 905 # Local Variables: 906 # mode: python 907 # indent-tabs-mode: nil 908 # fill-column: 72 909 # End: 910

qmtest-2.4.1/share/doc/qmtest/html/manual/string-pysrc.html0000664000076400007640000047701011122067155023337 0ustar stefanstefan string
Module string
[hide private]
[frames] | no frames]

Source Code for Module string

  1  """A collection of string operations (most are no longer used). 
  2   
  3  Warning: most of the code you see here isn't normally used nowadays. 
  4  Beginning with Python 1.6, many of these functions are implemented as 
  5  methods on the standard string object. They used to be implemented by 
  6  a built-in module called strop, but strop is now obsolete itself. 
  7   
  8  Public module variables: 
  9   
 10  whitespace -- a string containing all characters considered whitespace 
 11  lowercase -- a string containing all characters considered lowercase letters 
 12  uppercase -- a string containing all characters considered uppercase letters 
 13  letters -- a string containing all characters considered letters 
 14  digits -- a string containing all characters considered decimal digits 
 15  hexdigits -- a string containing all characters considered hexadecimal digits 
 16  octdigits -- a string containing all characters considered octal digits 
 17  punctuation -- a string containing all characters considered punctuation 
 18  printable -- a string containing all characters considered printable 
 19   
 20  """ 
 21   
 22  # Some strings for ctype-style character classification 
 23  whitespace = ' \t\n\r\v\f' 
 24  lowercase = 'abcdefghijklmnopqrstuvwxyz' 
 25  uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 
 26  letters = lowercase + uppercase 
 27  ascii_lowercase = lowercase 
 28  ascii_uppercase = uppercase 
 29  ascii_letters = ascii_lowercase + ascii_uppercase 
 30  digits = '0123456789' 
 31  hexdigits = digits + 'abcdef' + 'ABCDEF' 
 32  octdigits = '01234567' 
 33  punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~""" 
 34  printable = digits + letters + punctuation + whitespace 
 35   
 36  # Case conversion helpers 
 37  # Use str to convert Unicode literal in case of -U 
 38  l = map(chr, xrange(256)) 
 39  _idmap = str('').join(l) 
 40  del l 
 41   
 42  # Functions which aren't available as string methods. 
 43   
 44  # Capitalize the words in a string, e.g. " aBc  dEf " -> "Abc Def". 
45 -def capwords(s, sep=None):
46 """capwords(s, [sep]) -> string 47 48 Split the argument into words using split, capitalize each 49 word using capitalize, and join the capitalized words using 50 join. Note that this replaces runs of whitespace characters by 51 a single space. 52 53 """ 54 return (sep or ' ').join([x.capitalize() for x in s.split(sep)])
55 56 57 # Construct a translation string 58 _idmapL = None
59 -def maketrans(fromstr, tostr):
60 """maketrans(frm, to) -> string 61 62 Return a translation table (a string of 256 bytes long) 63 suitable for use in string.translate. The strings frm and to 64 must be of the same length. 65 66 """ 67 if len(fromstr) != len(tostr): 68 raise ValueError, "maketrans arguments must have same length" 69 global _idmapL 70 if not _idmapL: 71 _idmapL = map(None, _idmap) 72 L = _idmapL[:] 73 fromstr = map(ord, fromstr) 74 for i in range(len(fromstr)): 75 L[fromstr[i]] = tostr[i] 76 return ''.join(L)
77 78 79 80 #################################################################### 81 import re as _re 82
83 -class _multimap:
84 """Helper class for combining multiple mappings. 85 86 Used by .{safe_,}substitute() to combine the mapping and keyword 87 arguments. 88 """
89 - def __init__(self, primary, secondary):
90 self._primary = primary 91 self._secondary = secondary
92
93 - def __getitem__(self, key):
94 try: 95 return self._primary[key] 96 except KeyError: 97 return self._secondary[key]
98 99
100 -class _TemplateMetaclass(type):
101 pattern = r""" 102 %(delim)s(?: 103 (?P<escaped>%(delim)s) | # Escape sequence of two delimiters 104 (?P<named>%(id)s) | # delimiter and a Python identifier 105 {(?P<braced>%(id)s)} | # delimiter and a braced identifier 106 (?P<invalid>) # Other ill-formed delimiter exprs 107 ) 108 """ 109
110 - def __init__(cls, name, bases, dct):
111 super(_TemplateMetaclass, cls).__init__(name, bases, dct) 112 if 'pattern' in dct: 113 pattern = cls.pattern 114 else: 115 pattern = _TemplateMetaclass.pattern % { 116 'delim' : _re.escape(cls.delimiter), 117 'id' : cls.idpattern, 118 } 119 cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
120 121
122 -class Template:
123 """A string class for supporting $-substitutions.""" 124 __metaclass__ = _TemplateMetaclass 125 126 delimiter = '$' 127 idpattern = r'[_a-z][_a-z0-9]*' 128
129 - def __init__(self, template):
130 self.template = template
131 132 # Search for $$, $identifier, ${identifier}, and any bare $'s 133
134 - def _invalid(self, mo):
135 i = mo.start('invalid') 136 lines = self.template[:i].splitlines(True) 137 if not lines: 138 colno = 1 139 lineno = 1 140 else: 141 colno = i - len(''.join(lines[:-1])) 142 lineno = len(lines) 143 raise ValueError('Invalid placeholder in string: line %d, col %d' % 144 (lineno, colno))
145
146 - def substitute(self, *args, **kws):
147 if len(args) > 1: 148 raise TypeError('Too many positional arguments') 149 if not args: 150 mapping = kws 151 elif kws: 152 mapping = _multimap(kws, args[0]) 153 else: 154 mapping = args[0] 155 # Helper function for .sub() 156 def convert(mo): 157 # Check the most common path first. 158 named = mo.group('named') or mo.group('braced') 159 if named is not None: 160 val = mapping[named] 161 # We use this idiom instead of str() because the latter will 162 # fail if val is a Unicode containing non-ASCII characters. 163 return '%s' % (val,) 164 if mo.group('escaped') is not None: 165 return self.delimiter 166 if mo.group('invalid') is not None: 167 self._invalid(mo) 168 raise ValueError('Unrecognized named group in pattern', 169 self.pattern)
170 return self.pattern.sub(convert, self.template)
171
172 - def safe_substitute(self, *args, **kws):
173 if len(args) > 1: 174 raise TypeError('Too many positional arguments') 175 if not args: 176 mapping = kws 177 elif kws: 178 mapping = _multimap(kws, args[0]) 179 else: 180 mapping = args[0] 181 # Helper function for .sub() 182 def convert(mo): 183 named = mo.group('named') 184 if named is not None: 185 try: 186 # We use this idiom instead of str() because the latter 187 # will fail if val is a Unicode containing non-ASCII 188 return '%s' % (mapping[named],) 189 except KeyError: 190 return self.delimiter + named 191 braced = mo.group('braced') 192 if braced is not None: 193 try: 194 return '%s' % (mapping[braced],) 195 except KeyError: 196 return self.delimiter + '{' + braced + '}' 197 if mo.group('escaped') is not None: 198 return self.delimiter 199 if mo.group('invalid') is not None: 200 return self.delimiter 201 raise ValueError('Unrecognized named group in pattern', 202 self.pattern)
203 return self.pattern.sub(convert, self.template) 204 205 206 207 #################################################################### 208 # NOTE: Everything below here is deprecated. Use string methods instead. 209 # This stuff will go away in Python 3.0. 210 211 # Backward compatible names for exceptions 212 index_error = ValueError 213 atoi_error = ValueError 214 atof_error = ValueError 215 atol_error = ValueError 216 217 # convert UPPER CASE letters to lower case
218 -def lower(s):
219 """lower(s) -> string 220 221 Return a copy of the string s converted to lowercase. 222 223 """ 224 return s.lower()
225 226 # Convert lower case letters to UPPER CASE
227 -def upper(s):
228 """upper(s) -> string 229 230 Return a copy of the string s converted to uppercase. 231 232 """ 233 return s.upper()
234 235 # Swap lower case letters and UPPER CASE
236 -def swapcase(s):
237 """swapcase(s) -> string 238 239 Return a copy of the string s with upper case characters 240 converted to lowercase and vice versa. 241 242 """ 243 return s.swapcase()
244 245 # Strip leading and trailing tabs and spaces
246 -def strip(s, chars=None):
247 """strip(s [,chars]) -> string 248 249 Return a copy of the string s with leading and trailing 250 whitespace removed. 251 If chars is given and not None, remove characters in chars instead. 252 If chars is unicode, S will be converted to unicode before stripping. 253 254 """ 255 return s.strip(chars)
256 257 # Strip leading tabs and spaces
258 -def lstrip(s, chars=None):
259 """lstrip(s [,chars]) -> string 260 261 Return a copy of the string s with leading whitespace removed. 262 If chars is given and not None, remove characters in chars instead. 263 264 """ 265 return s.lstrip(chars)
266 267 # Strip trailing tabs and spaces
268 -def rstrip(s, chars=None):
269 """rstrip(s [,chars]) -> string 270 271 Return a copy of the string s with trailing whitespace removed. 272 If chars is given and not None, remove characters in chars instead. 273 274 """ 275 return s.rstrip(chars)
276 277 278 # Split a string into a list of space/tab-separated words
279 -def split(s, sep=None, maxsplit=-1):
280 """split(s [,sep [,maxsplit]]) -> list of strings 281 282 Return a list of the words in the string s, using sep as the 283 delimiter string. If maxsplit is given, splits at no more than 284 maxsplit places (resulting in at most maxsplit+1 words). If sep 285 is not specified or is None, any whitespace string is a separator. 286 287 (split and splitfields are synonymous) 288 289 """ 290 return s.split(sep, maxsplit)
291 splitfields = split 292 293 # Split a string into a list of space/tab-separated words
294 -def rsplit(s, sep=None, maxsplit=-1):
295 """rsplit(s [,sep [,maxsplit]]) -> list of strings 296 297 Return a list of the words in the string s, using sep as the 298 delimiter string, starting at the end of the string and working 299 to the front. If maxsplit is given, at most maxsplit splits are 300 done. If sep is not specified or is None, any whitespace string 301 is a separator. 302 """ 303 return s.rsplit(sep, maxsplit)
304 305 # Join fields with optional separator
306 -def join(words, sep = ' '):
307 """join(list [,sep]) -> string 308 309 Return a string composed of the words in list, with 310 intervening occurrences of sep. The default separator is a 311 single space. 312 313 (joinfields and join are synonymous) 314 315 """ 316 return sep.join(words)
317 joinfields = join 318 319 # Find substring, raise exception if not found
320 -def index(s, *args):
321 """index(s, sub [,start [,end]]) -> int 322 323 Like find but raises ValueError when the substring is not found. 324 325 """ 326 return s.index(*args)
327 328 # Find last substring, raise exception if not found
329 -def rindex(s, *args):
330 """rindex(s, sub [,start [,end]]) -> int 331 332 Like rfind but raises ValueError when the substring is not found. 333 334 """ 335 return s.rindex(*args)
336 337 # Count non-overlapping occurrences of substring
338 -def count(s, *args):
339 """count(s, sub[, start[,end]]) -> int 340 341 Return the number of occurrences of substring sub in string 342 s[start:end]. Optional arguments start and end are 343 interpreted as in slice notation. 344 345 """ 346 return s.count(*args)
347 348 # Find substring, return -1 if not found
349 -def find(s, *args):
350 """find(s, sub [,start [,end]]) -> in 351 352 Return the lowest index in s where substring sub is found, 353 such that sub is contained within s[start,end]. Optional 354 arguments start and end are interpreted as in slice notation. 355 356 Return -1 on failure. 357 358 """ 359 return s.find(*args)
360 361 # Find last substring, return -1 if not found
362 -def rfind(s, *args):
363 """rfind(s, sub [,start [,end]]) -> int 364 365 Return the highest index in s where substring sub is found, 366 such that sub is contained within s[start,end]. Optional 367 arguments start and end are interpreted as in slice notation. 368 369 Return -1 on failure. 370 371 """ 372 return s.rfind(*args)
373 374 # for a bit of speed 375 _float = float 376 _int = int 377 _long = long 378 379 # Convert string to float
380 -def atof(s):
381 """atof(s) -> float 382 383 Return the floating point number represented by the string s. 384 385 """ 386 return _float(s)
387 388 389 # Convert string to integer
390 -def atoi(s , base=10):
391 """atoi(s [,base]) -> int 392 393 Return the integer represented by the string s in the given 394 base, which defaults to 10. The string s must consist of one 395 or more digits, possibly preceded by a sign. If base is 0, it 396 is chosen from the leading characters of s, 0 for octal, 0x or 397 0X for hexadecimal. If base is 16, a preceding 0x or 0X is 398 accepted. 399 400 """ 401 return _int(s, base)
402 403 404 # Convert string to long integer
405 -def atol(s, base=10):
406 """atol(s [,base]) -> long 407 408 Return the long integer represented by the string s in the 409 given base, which defaults to 10. The string s must consist 410 of one or more digits, possibly preceded by a sign. If base 411 is 0, it is chosen from the leading characters of s, 0 for 412 octal, 0x or 0X for hexadecimal. If base is 16, a preceding 413 0x or 0X is accepted. A trailing L or l is not accepted, 414 unless base is 0. 415 416 """ 417 return _long(s, base)
418 419 420 # Left-justify a string
421 -def ljust(s, width, *args):
422 """ljust(s, width[, fillchar]) -> string 423 424 Return a left-justified version of s, in a field of the 425 specified width, padded with spaces as needed. The string is 426 never truncated. If specified the fillchar is used instead of spaces. 427 428 """ 429 return s.ljust(width, *args)
430 431 # Right-justify a string
432 -def rjust(s, width, *args):
433 """rjust(s, width[, fillchar]) -> string 434 435 Return a right-justified version of s, in a field of the 436 specified width, padded with spaces as needed. The string is 437 never truncated. If specified the fillchar is used instead of spaces. 438 439 """ 440 return s.rjust(width, *args)
441 442 # Center a string
443 -def center(s, width, *args):
444 """center(s, width[, fillchar]) -> string 445 446 Return a center version of s, in a field of the specified 447 width. padded with spaces as needed. The string is never 448 truncated. If specified the fillchar is used instead of spaces. 449 450 """ 451 return s.center(width, *args)
452 453 # Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03' 454 # Decadent feature: the argument may be a string or a number 455 # (Use of this is deprecated; it should be a string as with ljust c.s.)
456 -def zfill(x, width):
457 """zfill(x, width) -> string 458 459 Pad a numeric string x with zeros on the left, to fill a field 460 of the specified width. The string x is never truncated. 461 462 """ 463 if not isinstance(x, basestring): 464 x = repr(x) 465 return x.zfill(width)
466 467 # Expand tabs in a string. 468 # Doesn't take non-printing chars into account, but does understand \n.
469 -def expandtabs(s, tabsize=8):
470 """expandtabs(s [,tabsize]) -> string 471 472 Return a copy of the string s with all tab characters replaced 473 by the appropriate number of spaces, depending on the current 474 column, and the tabsize (default 8). 475 476 """ 477 return s.expandtabs(tabsize)
478 479 # Character translation through look-up table.
480 -def translate(s, table, deletions=""):
481 """translate(s,table [,deletions]) -> string 482 483 Return a copy of the string s, where all characters occurring 484 in the optional argument deletions are removed, and the 485 remaining characters have been mapped through the given 486 translation table, which must be a string of length 256. The 487 deletions argument is not allowed for Unicode strings. 488 489 """ 490 if deletions: 491 return s.translate(table, deletions) 492 else: 493 # Add s[:0] so that if s is Unicode and table is an 8-bit string, 494 # table is converted to Unicode. This means that table *cannot* 495 # be a dictionary -- for that feature, use u.translate() directly. 496 return s.translate(table + s[:0])
497 498 # Capitalize a string, e.g. "aBc dEf" -> "Abc def".
499 -def capitalize(s):
500 """capitalize(s) -> string 501 502 Return a copy of the string s with only its first character 503 capitalized. 504 505 """ 506 return s.capitalize()
507 508 # Substring replacement (global)
509 -def replace(s, old, new, maxsplit=-1):
510 """replace (str, old, new[, maxsplit]) -> string 511 512 Return a copy of string str with all occurrences of substring 513 old replaced by new. If the optional argument maxsplit is 514 given, only the first maxsplit occurrences are replaced. 515 516 """ 517 return s.replace(old, new, maxsplit)
518 519 520 # Try importing optional built-in module "strop" -- if it exists, 521 # it redefines some string operations that are 100-1000 times faster. 522 # It also defines values for whitespace, lowercase and uppercase 523 # that match <ctype.h>'s definitions. 524 525 try: 526 from strop import maketrans, lowercase, uppercase, whitespace 527 letters = lowercase + uppercase 528 except ImportError: 529 pass # Use the original versions 530

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python.ExecTest-class.html0000664000076400007640000004344711122067147030074 0ustar stefanstefan qm.test.classes.python.ExecTest
Package qm :: Package test :: Package classes :: Module python :: Class ExecTest
[hide private]
[frames] | no frames]

Class ExecTest

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
                  test.Test --+
                              |
                             ExecTest

Check that a Python expression evaluates to true.

An 'ExecTest' test consists of Python source code together with an (optional) Python expression. First the Python code is executed. If it throws an (uncaught) exception the test fails. If the optional expression is present, it is then evaluated. If it evaluates to false, the test fails. Otherwise, the test passes.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "source", title= "Pytho...
A list of the arguments to the extension class.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

Overrides: test.Test.Run
(inherited documentation)

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "source", title= "Python Source Code", desc\
ription= """The source code.

            This code may contain class definitions, function
            definitions, statements, and so forth.  If this code
            throws an uncaught exception, the test will fail.""", verb\
atim= "true", multiline= "true", default_value= "pass"), qm.fields.Tex\
tField(name= "expression", title= "Python Expression", description= ""\
...

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.execution_engine-module.html0000664000076400007640000000235211122067144027652 0ustar stefanstefan execution_engine

Module execution_engine


Classes

ExecutionEngine
TerminationRequested

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.config-module.html0000664000076400007640000001337011122067145024031 0ustar stefanstefan qm.config
Package qm :: Module config
[hide private]
[frames] | no frames]

Module config

source code

Variables [hide private]
  version = 'snapshot'
  data_dir = 'share/qmtest'
  doc_dir = 'share/doc/qmtest'
  extension_path = 'qm/test/classes'
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python_label.PythonLabel-class.html0000664000076400007640000002375211122067147031725 0ustar stefanstefan qm.test.classes.python_label.PythonLabel
Package qm :: Package test :: Package classes :: Module python_label :: Class PythonLabel
[hide private]
[frames] | no frames]

Class PythonLabel

source code

label.Label --+
              |
             PythonLabel

A 'PythonLabel' is a 'Label' that uses the 'a.b.c' naming scheme.

A 'PythonLabel' is a 'Label' whose separator character is the period and whose components consist of lower-case letters, numerals, and underscores. These labels have the property that they can be easily mapped to filenames on most operating systems; all valid labels are valid filenames (replacing '.' with '/') and two different labels will always map to two different filenames.

Instance Methods [hide private]
 
IsValid(self, label, is_component)
Returns true if this label is not valid.
source code

Inherited from label.Label: Basename, Dirname, Join, Split, SplitLeft, __init__, __str__

Class Variables [hide private]
  _sep = '.'
The separator character used to separate components.
  __valid_label_regexp = re.compile(r'[-a-z0-9_\.]+$')
A compiled regular expression that matches valid labels.
Method Details [hide private]

IsValid(self, label, is_component)

source code 

Returns true if this label is not valid.

returns -- True if this label is not valid.

Overrides: label.Label.IsValid

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-U.html0000664000076400007640000002744311122067144024323 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

U



././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_result_stream.XMLResultStream-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_result_stream.XMLResultStream-class.ht0000664000076400007640000005153111122067150033245 0ustar stefanstefan qm.test.classes.xml_result_stream.XMLResultStream
Package qm :: Package test :: Package classes :: Module xml_result_stream :: Class XMLResultStream
[hide private]
[frames] | no frames]

Class XMLResultStream

source code

                 object --+            
                          |            
        extension.Extension --+        
                              |        
     result_stream.ResultStream --+    
                                  |    
file_result_stream.FileResultStream --+
                                      |
                                     XMLResultStream

An 'XMLResultStream' writes out results as XML.

An 'XMLResultStream' writes out results as XML. This stream is used to write out QMTest results files. The DTD is designed in such a way that if QMTest is terminated in the middle of a test run, the file will still be nearly valid, as long as the interruption did not occur in the midst of writing out an individual result. The closing tag for the results file will be missing.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code
 
WriteAnnotation(self, key, value)
Output an annotation for this run.
source code
 
WriteResult(self, result)
Output a test result.
source code
 
Summarize(self)
Output summary information about the results.
source code

Inherited from result_stream.ResultStream: WriteAllAnnotations

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from file_result_stream.FileResultStream: arguments, file, filename

Inherited from result_stream.ResultStream: expected_outcomes, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

WriteAnnotation(self, key, value)

source code 

Output an annotation for this run.

Subclasses should override this if they want to store/display annotations; the default implementation simply discards them.

'key' -- the key value as a string.

'value' -- the value of this annotation as a string.

Overrides: result_stream.ResultStream.WriteAnnotation
(inherited documentation)

WriteResult(self, result)

source code 

Output a test result.

Subclasses must override this method; the default implementation raises a 'NotImplementedError'.

'result' -- A 'Result'.

Overrides: result_stream.ResultStream.WriteResult
(inherited documentation)

Summarize(self)

source code 

Output summary information about the results.

When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point.

Derived class methods may override this method. They should, however, invoke this version before returning.

Overrides: result_stream.ResultStream.Summarize
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.DtmlPage-class.html0000664000076400007640000010264711122067151024660 0ustar stefanstefan qm.web.DtmlPage
Package qm :: Module web :: Class DtmlPage
[hide private]
[frames] | no frames]

Class DtmlPage

source code

Known Subclasses:

Base class for classes to generate web pages from DTML.

The 'DtmlPage' object is used as the variable context when generating HTML from DTML. Attributes and methods are available as variables in DTML expressions.

This base class contains common variables and functions that are available when generating all DTML files.

To generate HTML from a DTML template, instantiate a 'DtmlPage' object, passing the name of the DTML template file to the initializer function (or create a subclass which does this automatically). Additional named attributes specified in the initializer functions are set as attributes of the 'DtmlPage' object, and thus available as variables in DTML Python expressions.

To generate HTML from the template, use the '__call__' method, passing a 'WebRequest' object representing the request in response to which the HTML page is being generated. The request set as the 'request' attribute of the 'DtmlPage' object. The 'WebRequest' object may be omitted, if the generated HTML page is generic and requires no information specific to the request or web session; in this case, an empty request object is used.

This class also has an attribute, 'default_class', which is the default 'DtmlPage' subclass to use when generating HTML. By default, it is initialized to 'DtmlPage' itself, but applications may derive a 'DtmlPage' subclass and point 'default_class' to it to obtain customized versions of standard pages.

Nested Classes [hide private]
  default_class
Base class for classes to generate web pages from DTML.
Instance Methods [hide private]
 
__init__(self, dtml_template, **attributes)
Create a new page.
source code
 
__call__(self, request=None)
Generate an HTML page from the DTML template.
source code
 
GetProgramName(self)
Return the name of this application program.
source code
 
GetMainPageUrl(self)
Return the URL for the main page.
source code
 
WebRequest(self, script_url, **fields)
Convenience constructor for 'WebRequest' objects.
source code
 
GenerateXMLHeader(self)
Return the XML header for the document.
source code
 
GenerateHtmlHeader(self, description, headers='')
Return the header for an HTML document.
source code
 
GenerateStartBody(self, decorations=1)
Return markup to start the body of the HTML document.
source code
 
GenerateEndBody(self, decorations=1)
Return markup to end the body of the HTML document.
source code
 
GenerateStartScript(self, uri=None)
Return the HTML for beginning a script.
source code
 
GenerateEndScript(self)
Return the HTML for ending an embedded script.
source code
 
MakeLoginForm(self, redirect_request=None, default_user_id='') source code
 
MakeButton(self, title, script_url, css_class=None, **fields)
Generate HTML for a button to load a URL.
source code
 
MakeImageUrl(self, image)
Generate a URL for an image.
source code
 
MakeSpacer(self, width=1, height=1)
Generate a spacer.
source code
 
MakeRule(self, color='black')
Generate a plain horizontal rule.
source code
 
UserIsInGroup(self, group_id)
Return true if the user is a member of group 'group_id'.
source code
Class Variables [hide private]
  html_stylesheet = '/stylesheets/qm.css'
The URL for the cascading stylesheet to use with generated pages.
  common_javascript = '/common.js'
  qm_bug_system_url = 'mailto:qmtest@codesourcery.com'
The public URL for the bug tracking system for the QM tools.
  web
Common code for implementing web user interfaces.
Method Details [hide private]

__init__(self, dtml_template, **attributes)
(Constructor)

source code 

Create a new page.

'dtml_template' -- The file name of the DTML template from which the page is generated. The file is assumed to reside in the 'dtml' subdirectory of the configured share directory.

'**attributes' -- Additional attributes to include in the variable context.

__call__(self, request=None)
(Call operator)

source code 

Generate an HTML page from the DTML template.

'request' -- A 'WebRequest' object containing a page request in response to which an HTML page is being generated. Session information from the request may be used when generating the page. The request may be 'None', if none is available.

returns -- The generated HTML text.

WebRequest(self, script_url, **fields)

source code 

Convenience constructor for 'WebRequest' objects.

Constructs a 'WebRequest' using the specified 'script_url' and 'fields', using the request associated with this object as the base request.

GenerateHtmlHeader(self, description, headers='')

source code 

Return the header for an HTML document.

'description' -- A string describing this page.

'headers' -- Any additional HTML headers to place in the '<head>' section of the HTML document.

GenerateStartScript(self, uri=None)

source code 

Return the HTML for beginning a script.

'uri' -- If not None, a string giving the URI of the script.

returns -- A string consisting of HTML for beginning an embedded script.

'GenerateEndScript' must be called later to terminate the script.

GenerateEndScript(self)

source code 

Return the HTML for ending an embedded script.

returns -- A string consisting of HTML for ending an embedded script.

MakeButton(self, title, script_url, css_class=None, **fields)

source code 

Generate HTML for a button to load a URL.

'title' -- The button title.

'script_url' -- The URL of the script.

'fields' -- Additional fields to add to the script request.

'css_class' -- The CSS class to use for the button, or 'None'.

The resulting HTML must be included in a form.

MakeSpacer(self, width=1, height=1)

source code 

Generate a spacer.

'width' -- The width of the spacer, in pixels.

'height' -- The height of the spacer, in pixels.

returns -- A transparent image of the requested size.

UserIsInGroup(self, group_id)

source code 

Return true if the user is a member of group 'group_id'.

Checks the group membership of the user associated with the current session.

If there is no group named 'group_id' in the user database, returns a false result.


Class Variable Details [hide private]

web

Common code for implementing web user interfaces.

Value:
qm.web

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.file_database-module.html0000664000076400007640000000232211122067144027062 0ustar stefanstefan file_database

Module file_database


Classes

ExtensionDatabase
FileDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler-module.html0000664000076400007640000001477711122067145027024 0ustar stefanstefan qm.test.classes.compiler
Package qm :: Package test :: Package classes :: Module compiler
[hide private]
[frames] | no frames]

Module compiler

source code

Uniform interface to compilers.

This module contains the 'Compiler' class which is an abstract base class providing a uniform interface to various compilers, such as the GNU Compiler Collection and the Edison Design Group compilers.

Classes [hide private]
  CompilerExecutable
A 'CompilerExecutable' is a 'Compiler' that is being run.
  Compiler
A 'Compiler' compiles and links source files.
  SourcePosition
A 'SourcePosition' indicates a location in source code.
  Diagnostic
A 'Diagnostic' is a message issued by a compiler.
  GCC
A 'GCC' is a GNU Compiler Collection compiler.
  EDG
An 'EDG' is an Edison Design Group compiler.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.distribution.Distribution-class.html0000664000076400007640000002407611122067146030551 0ustar stefanstefan qm.dist.distribution.Distribution
Package qm :: Package dist :: Module distribution :: Class Distribution
[hide private]
[frames] | no frames]

Class Distribution

source code

distutils.dist.Distribution --+
                              |
                             Distribution

Instance Methods [hide private]
 
__init__(self, attrs=None)
Construct a new Distribution instance: initialize all the attributes of a Distribution, and then use 'attrs' (a dictionary mapping attribute names to values) to assign some of those attributes their "real" values.
source code

Inherited from distutils.dist.Distribution: announce, dump_option_dicts, finalize_options, find_config_files, get_command_class, get_command_list, get_command_obj, get_command_packages, get_option_dict, handle_display_options, has_c_libraries, has_data_files, has_ext_modules, has_headers, has_modules, has_pure_modules, has_scripts, is_pure, parse_command_line, parse_config_files, print_command_list, print_commands, reinitialize_command, run_command, run_commands

Inherited from distutils.dist.Distribution (private): _get_toplevel_options, _parse_command_opts, _set_command_options, _show_help

Class Variables [hide private]

Inherited from distutils.dist.Distribution: common_usage, display_option_names, display_options, global_options, negative_opt

Method Details [hide private]

__init__(self, attrs=None)
(Constructor)

source code 

Construct a new Distribution instance: initialize all the attributes of a Distribution, and then use 'attrs' (a dictionary mapping attribute names to values) to assign some of those attributes their "real" values. (Any attributes not mentioned in 'attrs' will be assigned to some null value: 0, None, an empty list or dictionary, etc.) Most importantly, initialize the 'command_obj' attribute to the empty dictionary; this will be filled in with real command objects by 'parse_command_line()'.

Overrides: distutils.dist.Distribution.__init__
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.reader_test_run-module.html0000664000076400007640000001116311122067145026725 0ustar stefanstefan qm.test.reader_test_run
Package qm :: Package test :: Module reader_test_run
[hide private]
[frames] | no frames]

Module reader_test_run

source code

Classes [hide private]
  ReaderTestRun
A 'ReaderTestRun' reads its results using a 'ResultReader'.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.base-pysrc.html0000664000076400007640000062771111122067161024337 0ustar stefanstefan qm.test.base
Package qm :: Package test :: Module base
[hide private]
[frames] | no frames]

Source Code for Module qm.test.base

  1  ######################################################################## 
  2  # 
  3  # File:   base.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-03-08 
  6  # 
  7  # Contents: 
  8  #   Base interfaces and classes. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import cPickle 
 21  import cStringIO 
 22  import os 
 23  import qm 
 24  import qm.attachment 
 25  from   qm.common import * 
 26  from   qm.test.file_result_reader import FileResultReader 
 27  from   qm.test.expectation_database import ExpectationDatabase 
 28  import qm.platform 
 29  import qm.structured_text 
 30  from   qm.test.context import * 
 31  from   qm.test.result import * 
 32  import qm.xmlutil 
 33  import string 
 34  import sys 
 35  import tempfile 
 36  import types 
 37   
 38  ######################################################################## 
 39  # Exceptions 
 40  ######################################################################## 
 41   
42 -class CouldNotLoadExtensionError(QMException):
43 """An exception indicating that an extension class could not be loaded.""" 44
45 - def __init__(self, class_name, exc_info):
46 """Construct a new 'CouldNotLoadExtensionError'. 47 48 'class_name' -- The name of the class. 49 50 'exc_info' -- An exception tuple, as returned by 'sys.exc_info'.""" 51 52 self.exc_info = exc_info 53 message = qm.common.format_exception(exc_info) 54 message += "\n" + qm.error("could not load extension class", 55 class_name = class_name) 56 QMException.__init__(self, message)
57 58 ######################################################################## 59 # Functions 60 ######################################################################## 61
62 -def get_extension_directories(kind, database, database_path = None):
63 """Return the directories to search for QMTest extensions. 64 65 'kind' -- A string giving kind of extension for which we are looking. 66 This must be of the elements of 'extension_kinds'. 67 68 'database' -- The 'Database' with which the extension class will be 69 used, or 'None'. 70 71 'database_path' -- The path from which the database will be loaded. 72 If 'None', 'database.GetPath()' is used. 73 74 returns -- A sequence of strings. Each string is the path to a 75 directory that should be searched for QMTest extensions. The 76 directories must be searched in order; the first directory 77 containing the desired module is the one from which the module is 78 loaded. 79 80 The directories that are returned are, in order: 81 82 1. Those directories present in the 'QMTEST_CLASS_PATH' environment 83 variable. 84 85 2. Those directories specified by the 'GetClassPaths' method on the 86 test database -- unless 'kind' is 'database'. 87 88 3. The directory specified by config.extension_path. 89 90 4. The directories containing classes that come with QMTest. 91 92 By placing the 'QMTEST_CLASS_PATH' directories first, users can 93 override test classes with standard names.""" 94 95 global extension_kinds 96 97 # The kind should be one of the extension_kinds. 98 assert kind in extension_kinds 99 100 # Start with the directories that the user has specified in the 101 # QMTEST_CLASS_PATH environment variable. 102 if os.environ.has_key('QMTEST_CLASS_PATH'): 103 dirs = string.split(os.environ['QMTEST_CLASS_PATH'], 104 os.pathsep) 105 else: 106 dirs = [] 107 108 # Search directories specified by the database. 109 if database: 110 dirs = dirs + database.GetClassPaths() 111 112 # Search the database configuration directory. 113 if database: 114 dirs.append(database.GetConfigurationDirectory()) 115 elif database_path: 116 dirs.append(qm.test.database.get_configuration_directory 117 (database_path)) 118 119 # Search qmtest's own site-extensions directory. 120 dirs.append(os.path.join(qm.prefix, qm.extension_path)) 121 122 dirs.append(qm.common.get_lib_directory('test', 'classes')) 123 124 return dirs
125 126
128 """Return the names of QMTest extension classes in 'directory'. 129 130 'directory' -- A string giving the path to a directory in the file 131 system. 132 133 returns -- A dictionary mapping the strings in 'extension_kinds' to 134 sequences of strings. Each element in the sequence names an 135 extension class, using the form 'module.class'""" 136 137 global extension_kinds 138 139 # Assume that there are no extension classes in this directory. 140 extensions = {} 141 for kind in extension_kinds: 142 extensions[kind] = [] 143 144 # Look for a file named 'classes.qmc' in this directory. 145 file = os.path.join(directory, 'classes.qmc') 146 # If the file does not exist, there are no extension classes in 147 # this directory. 148 if not os.path.isfile(file): 149 return extensions 150 151 try: 152 # Load the file. 153 document = qm.xmlutil.load_xml_file(file) 154 # Get the root node in the document. 155 root = document.documentElement 156 # Get the sequence of elements corresponding to each of the 157 # classes listed in the directory. 158 classes = root.getElementsByTagName("class") 159 # Go through each of the classes to see what kind it is. 160 for c in classes: 161 kind = c.getAttribute('kind') 162 # Skip extensions we do not understand. Perhaps they 163 # are for some other QM tool. 164 if kind not in extension_kinds: 165 continue 166 if c.hasAttribute("name"): 167 name = c.getAttribute("name") 168 else: 169 # Before QMTest 2.1, the class name was contained in 170 # the class element, rather than being an attribute. 171 name = qm.xmlutil.get_dom_text(c) 172 # Strip whitespace. 173 name = name.strip() 174 extensions[kind].append(name) 175 except: 176 raise 177 178 return extensions
179 180
181 -def get_extension_class_names(kind, database, database_path = None):
182 """Return the names of extension classes. 183 184 'kind' -- The kind of extension class. This value must be one 185 of the 'extension_kinds'. 186 187 'database' -- The 'Database' with which the extension class will be 188 used, or 'None' if 'kind' is 'database'. 189 190 'database_path' -- The path from which the database will be loaded. 191 If 'None', 'database.GetPath()' is used. 192 193 returns -- A sequence of strings giving the names of the extension 194 classes with the indicated 'kind', in the form 'module.class'.""" 195 196 dirs = get_extension_directories(kind, database, database_path) 197 names = [] 198 for d in dirs: 199 names.extend(get_extension_class_names_in_directory(d)[kind]) 200 return names
201 202
203 -def get_extension_class_from_directory(class_name, kind, directory, path):
204 """Load an extension class from 'directory'. 205 206 'class_name' -- The name of the extension class, in the form 207 'module.class'. 208 209 'kind' -- The kind of class to load. This value must be one 210 of the 'extension_kinds'. 211 212 'directory' -- The directory from which to load the class. 213 214 'path' -- The directories to search for modules imported by the new 215 module. 216 217 returns -- The class loaded.""" 218 219 global __class_caches 220 global __extension_bases 221 222 # If this class is already in the cache, we can just return it. 223 cache = __class_caches[kind] 224 if cache.has_key(class_name): 225 return cache[class_name] 226 227 # Load the class. 228 try: 229 klass = qm.common.load_class(class_name, [directory], 230 path + sys.path) 231 except: 232 raise CouldNotLoadExtensionError(class_name, sys.exc_info()) 233 234 # Make sure the class is derived from the appropriate base class. 235 if not issubclass(klass, __extension_bases[kind]): 236 raise QMException, \ 237 qm.error("extension class not subclass", 238 kind = kind, 239 class_name = class_name, 240 base_name = __extension_bases[kind].__name__) 241 242 # Cache it. 243 cache[class_name] = klass 244 245 return klass
246 247
248 -def get_extension_class(class_name, kind, database, database_path = None):
249 """Return the extension class named 'class_name'. 250 251 'class_name' -- The name of the class, in the form 'module.class'. 252 253 'kind' -- The kind of class to load. This value must be one 254 of the 'extension_kinds'. 255 256 'database' -- The 'Database' with which the extension class will be 257 used, or 'None' if 'kind' is 'database'. 258 259 'database_path' -- The path from which the database will be loaded. 260 If 'None', 'database.GetPath()' is used. 261 262 returns -- The class object with the indicated 'class_name'.""" 263 264 global __class_caches 265 266 # If this class is already in the cache, we can just return it. 267 cache = __class_caches[kind] 268 if cache.has_key(class_name): 269 return cache[class_name] 270 271 # For backwards compatibility with QM 1.1.x, we accept 272 # "xmldb.Database" and "qm.test.xmldb.Database", even though those 273 # to do not name actual database classes any more. 274 if kind == "database" and class_name in ("xmldb.Database", 275 "qm.test.xmldb.Database"): 276 class_name = "xml_database.XMLDatabase" 277 278 # Look for the class in each of the extension directories. 279 directories = get_extension_directories(kind, database, database_path) 280 directory = None 281 for d in directories: 282 if class_name in get_extension_class_names_in_directory(d)[kind]: 283 directory = d 284 break 285 286 # If the class could not be found, issue an error. 287 if not directory: 288 raise QMException, qm.error("extension class not found", 289 klass=class_name) 290 291 # Load the class. 292 return get_extension_class_from_directory(class_name, kind, 293 directory, directories)
294 295
296 -def get_test_class(class_name, database):
297 """Return the test class named 'class_name'. 298 299 'class_name' -- The name of the test class, in the form 300 'module.class'. 301 302 returns -- The test class object with the indicated 'class_name'.""" 303 304 return get_extension_class(class_name, 'test', database)
305 306
307 -def get_resource_class(class_name, database):
308 """Return the resource class named 'class_name'. 309 310 'class_name' -- The name of the resource class, in the form 311 'module.class'. 312 313 returns -- The resource class object with the indicated 314 'class_name'.""" 315 316 return get_extension_class(class_name, 'resource', database)
317 318
319 -def get_extension_classes(kind, database = None):
320 """Return the extension classes for the given 'kind'. 321 322 'kind' -- The kind of extensions being sought. The value must be 323 one of the 'extension_kinds'. 324 325 'database' -- If not 'None', the test 'Database' in use. 326 327 returns -- A list of the available extension classes of the 328 indicated 'kind'.""" 329 330 classes = [] 331 directories = get_extension_directories(kind, database) 332 for d in directories: 333 names = get_extension_class_names_in_directory(d)[kind] 334 d_classes = [get_extension_class_from_directory(n, kind, d, 335 directories) 336 for n in names] 337 classes.extend(d_classes) 338 339 return classes
340 341
342 -def load_results(file, database):
343 """Read test results from a file. 344 345 'file' -- The filename or file object from which to read the 346 results. If 'file' is not a string, then it is must be a seekable 347 file object, and this function will look for a 'FileResultReader' 348 that accepts the file. If 'file' is a string, then it is treated as 349 either a filename or as an extension descriptor. 350 351 'database' -- The current database. 352 353 returns -- A 'ResultReader' object, or raises an exception if no 354 appropriate reader is available.""" 355 356 f = None 357 if isinstance(file, types.StringTypes): 358 if os.path.exists(file): 359 f = open(file, "rb") 360 else: 361 f = file 362 if f: 363 # Find the first FileResultStream that will accept this file. 364 for c in get_extension_classes("result_reader", database): 365 if issubclass(c, FileResultReader): 366 try: 367 return c({"file" : f}) 368 except FileResultReader.InvalidFile: 369 # Go back to the beginning of the file. 370 f.seek(0) 371 if not isinstance(file, types.StringTypes): 372 raise FileResultReader.InvalidFile, \ 373 "not a valid results file" 374 if database: 375 extension_loader = database.GetExtension 376 else: 377 extension_loader = None 378 class_loader = lambda n: get_extension_class(n, 379 "result_reader", 380 database) 381 cl, args = qm.extension.parse_descriptor(file, 382 class_loader, 383 extension_loader) 384 return cl(args)
385 386
387 -def load_expectations(file, database, annotations = None):
388 """Read expectations from a file. 389 390 'file' -- The filename or file object from which to read the 391 expectations. If 'file' is not a string, then it is must be a seekable 392 file object, and this function will look for an 'ExpectationDatabase' 393 that accepts the file. If 'file' is a string, then it is treated as 394 either a filename or as an extension descriptor. 395 396 'database' -- The current database. 397 398 'annotations' -- Annotations for the current test run. 399 400 returns -- An 'ExpectationDatabase' object, or raises an exception if no 401 appropriate reader is available.""" 402 403 if not file: 404 return ExpectationDatabase() 405 f = None 406 if isinstance(file, (str, unicode)): 407 if os.path.exists(file): 408 f = open(file, "rb") 409 else: 410 f = file 411 if f: 412 return PreviousTestRun(test_database = database, results_file = f) 413 if not isinstance(file, (str, unicode)): 414 raise QMException, "not a valid expectation database" 415 if database: 416 extension_loader = database.GetExtension 417 else: 418 extension_loader = None 419 class_loader = lambda n: get_extension_class(n, 420 "expectation_database", 421 database) 422 cl, args = qm.extension.parse_descriptor(file, 423 class_loader, 424 extension_loader) 425 args['test_database'] = database 426 args['testrun_parameters'] = annotations or {} 427 return cl(**args)
428 429
430 -def load_outcomes(file, database):
431 """Load test outcomes from a file. 432 433 'file' -- The file object from which to read the results. See 434 'load_results' for details. 435 436 'database' -- The current database. 437 438 returns -- A map from test IDs to outcomes.""" 439 440 results = load_results(file, database) 441 outcomes = {} 442 for r in results: 443 # Keep test outcomes only. 444 if r.GetKind() == Result.TEST: 445 outcomes[r.GetId()] = r.GetOutcome() 446 return outcomes
447 448
449 -def _result_from_dom(node):
450 """Extract a result from a DOM node. 451 452 'node' -- A DOM node corresponding to a "result" element. 453 454 returns -- A 'Result' object. The context for the result is 'None', 455 since context is not represented in a result DOM node.""" 456 457 assert node.tagName == "result" 458 # Extract the outcome. 459 outcome = qm.xmlutil.get_child_text(node, "outcome") 460 # Extract the test ID. 461 test_id = node.getAttribute("id") 462 kind = node.getAttribute("kind") 463 # Build a Result. 464 result = Result(kind, test_id, outcome) 465 # Extract properties, one for each property element. 466 for property_node in node.getElementsByTagName("property"): 467 # The name is stored in an attribute. 468 name = property_node.getAttribute("name") 469 # The value is stored in the child text node. 470 value = qm.xmlutil.get_dom_text(property_node) 471 # Store it. 472 result[name] = value 473 474 return result
475 476 477 ######################################################################## 478 # variables 479 ######################################################################## 480 481 import qm.test.database 482 import qm.label 483 import qm.host 484 import qm.test.resource 485 import qm.test.result_reader 486 import qm.test.result_stream 487 import qm.test.run_database 488 import qm.test.expectation_database 489 import qm.test.suite 490 import qm.test.target 491 import qm.test.test 492 from qm.test.classes.previous_testrun import PreviousTestRun 493 494 __extension_bases = { 495 'database' : qm.test.database.Database, 496 'host' : qm.host.Host, 497 'label' : qm.label.Label, 498 'resource' : qm.test.resource.Resource, 499 'result_reader' : qm.test.result_reader.ResultReader, 500 'result_stream' : qm.test.result_stream.ResultStream, 501 'run_database' : qm.test.run_database.RunDatabase, 502 'expectation_database' : qm.test.expectation_database.ExpectationDatabase, 503 'suite' : qm.test.suite.Suite, 504 'target' : qm.test.target.Target, 505 'test' : qm.test.test.Test 506 } 507 """A map from extension class kinds to base classes. 508 509 An extension class of a particular 'kind' must be derived from 510 'extension_bases[kind]'.""" 511 512 extension_kinds = __extension_bases.keys() 513 """Names of different kinds of QMTest extension classes.""" 514 extension_kinds.sort() 515 516 __class_caches = {} 517 """A dictionary of loaded class caches. 518 519 The keys are the kinds in 'extension_kinds'. The associated value 520 is itself a dictionary mapping class names to class objects.""" 521 522 # Initialize the caches. 523 for kind in extension_kinds: 524 __class_caches[kind] = {} 525 526 ######################################################################## 527 # Local Variables: 528 # mode: python 529 # indent-tabs-mode: nil 530 # fill-column: 72 531 # End: 532

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command.install_extensions-module.html0000664000076400007640000001746611122067145031102 0ustar stefanstefan qm.dist.command.install_extensions
Package qm :: Package dist :: Package command :: Module install_extensions
[hide private]
[frames] | no frames]

Module install_extensions

source code

Classes [hide private]
  install_extensions
Install extension files.
Functions [hide private]
 
_compare_files(a, b)
Compare the content of two files.
source code
Function Details [hide private]

_compare_files(a, b)

source code 

Compare the content of two files.

'a' -- Filename of first file to be compared.

'b' -- Filename of second file to be compared.

returns -- True if both files have the same content, False otherwise.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler_table.CompilerTable-class.html0000664000076400007640000004156311122067147032527 0ustar stefanstefan qm.test.classes.compiler_table.CompilerTable
Package qm :: Package test :: Package classes :: Module compiler_table :: Class CompilerTable
[hide private]
[frames] | no frames]

Class CompilerTable

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
          resource.Resource --+
                              |
                             CompilerTable

A map from programming languages to 'Compiler's.

The 'CompilerTable' resource uses the context to determine which
compilers the user wants to test.  Test databases containing
compiler tests should arrange for the tests they compain to depend
on a 'CompilerTable' resource.

The first context variable which is examined is
'CompilerTable.languages'.  The value should be a
whitespace-separated list of programming language names.  (See
below for standardized names for some languages.)

Then, for each language 'l' in the list of languages, the
following context variables are examined:

- 'CompilerTable.l_kind'

  The kind of compiler (e.g., "GCC" or "EDG") used to compile
  programs of language 'l'.  The 'kind' must name a class derived
  from 'Compiler'.

- 'CompilerTable.l_path'

  The path to the compiler for language 'l'.  This path may be
  either absolute or relative.

- 'CompilerTable.l_options'

  A whitespace-separated list of command-line options to provide
  to the compiler for language 'l'.  These options are passed to
  the constructor for the 'Compiler' object; generally, all tests
  are run with these options, followed by any test-specific
  options.  For example, if the user wants to test the compiler
  when run with '-O2', the user would put '-O2' in the 'l_options'
  context variable.

The 'CompilerTable' resource provides the following context
variables to all tests that depend upon the resource:

- 'CompilerTable.compilers'

   The 'compilers' variable is a map from language names to
   instances of 'Compiler'.  Test classes should obtain the
   'Compiler' to use when compiling source files by using this
   map.

- 'CompilerTable.target'

   An instance of 'Host' that can be used to run compiler
   programs.

Nested Classes [hide private]

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
SetUp(self, context, result)
Set up the resource.
source code

Inherited from resource.Resource: CleanUp

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  LANG_C = "c"
The name of the C programming language.
  LANG_CPLUSPLUS = "cplusplus"
The name of the C++ programming language.

Inherited from resource.Resource: kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, arguments, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

SetUp(self, context, result)

source code 

Set up the resource.

'context' -- A 'Context' giving run-time parameters to the resource. The resource may place additional variables into the 'context'; these variables will be visible to tests that depend on the resource.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

Overrides: resource.Resource.SetUp
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.temporary_directory-module.html0000664000076400007640000001110111122067145026660 0ustar stefanstefan qm.temporary_directory
Package qm :: Module temporary_directory
[hide private]
[frames] | no frames]

Module temporary_directory

source code

Classes [hide private]
  TemporaryDirectory
A 'TemporaryDirectory' is a directory for temporary files.
qmtest-2.4.1/share/doc/qmtest/html/manual/frames.html0000664000076400007640000000111011122067144022126 0ustar stefanstefan API Documentation qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_HTML.HTML-class.html0000664000076400007640000011214011122067146031370 0ustar stefanstefan qm.external.DocumentTemplate.DT_HTML.HTML
Package qm :: Package external :: Package DocumentTemplate :: Module DT_HTML :: Class HTML
[hide private]
[frames] | no frames]

Class HTML

source code

DT_String.String --+
                   |
                  HTML
Known Subclasses:

HTML Document Templates

HTML Document templates use HTML server-side-include syntax,
rather than Python format-string syntax.  Here's a simple example:

  <!--#in results-->
    <!--#var name-->
  <!--#/in-->

HTML document templates quote HTML tags in source when the
template is converted to a string.  This is handy when templates
are inserted into HTML editing forms.

Instance Methods [hide private]
 
tagre(self) source code
 
parseTag(self, match_ob, command=None, sargs='')
Parse a tag using an already matched re
source code
 
SubTemplate(self, name) source code
 
varExtra(self, match_ob) source code
 
manage_edit(self, data, REQUEST=None)
edit a template
source code
 
quotedHTML(self, text=None, character_entities=(('&', '&amp;'), ('<', '&lt;'), ('>', '&gt;'), ('"', '&quot;'))) source code
 
errQuote(self, text=None, character_entities=(('&', '&amp;'), ('<', '&lt;'), ('>', '&gt;'), ('"', '&quot;'))) source code
 
__str__(self) source code
 
management_interface(self)
Hook to allow public execution of management interface with everything else private.
source code
 
manage_editForm(self, URL1, REQUEST)
Display doc template editing form
source code
 
manage(self, URL1, REQUEST)
Display doc template editing form
source code
 
manage_editDocument(self, URL1, REQUEST)
Display doc template editing form
source code

Inherited from DT_String.String: ZDocumentTemplate_afterRender, ZDocumentTemplate_beforeRender, __call__, __getstate__, __init__, cook, default, id, initvars, munge, name, parse, parse_block, parse_close, parse_error, read, read_raw, setName, skip_eol, var

Inherited from DT_String.String (private): _parseTag

Class Variables [hide private]
  tagre__roles__ = ()
  parseTag__roles__ = ()
  SubTemplate__roles__ = ()
  varExtra__roles__ = ()
  manage_edit__roles__ = ()
  quotedHTML__roles__ = ()
  errQuote__roles__ = ()
  management_interface__roles__ = ()
  manage_editForm__roles__ = ()
  manage_editDocument__roles__ = ()
  manage__roles__ = ()

Inherited from DT_String.String: ZDocumentTemplate_afterRender__roles__, ZDocumentTemplate_beforeRender__roles__, _parseTag__roles__, commands, commands__roles__, cook__roles__, default__roles__, func_code, func_defaults, func_defaults__roles__, initvars__roles__, isDocTemp, munge__roles__, parse__roles__, parse_block__roles__, parse_close__roles__, parse_error__roles__, read__roles__, read_raw__roles__, setName__roles__, shared_globals, shared_globals__roles__, skip_eol__roles__, validate, validate__roles__, var__roles__

Method Details [hide private]

tagre(self)

source code 
Overrides: DT_String.String.tagre

parseTag(self, match_ob, command=None, sargs='')

source code 
Parse a tag using an already matched re

Return: tag, args, command, coname

where: tag is the tag,
       args is the tag's argument string,
       command is a corresponding command info structure if the
          tag is a start tag, or None otherwise, and
       coname is the name of a continue tag (e.g. else)
         or None otherwise

Overrides: DT_String.String.parseTag

SubTemplate(self, name)

source code 
Overrides: DT_String.String.SubTemplate

varExtra(self, match_ob)

source code 
Overrides: DT_String.String.varExtra

manage_edit(self, data, REQUEST=None)

source code 

edit a template

Overrides: DT_String.String.manage_edit

errQuote(self, text=None, character_entities=(('&', '&amp;'), ('<', '&lt;'), ('>', '&gt;'), ('"', '&quot;')))

source code 
Overrides: DT_String.String.errQuote

__str__(self)
(Informal representation operator)

source code 
Overrides: DT_String.String.__str__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.lock-module.html0000664000076400007640000000170111122067144024271 0ustar stefanstefan lock

Module lock



[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.database-module.html0000664000076400007640000000563211122067144026072 0ustar stefanstefan database

Module database


Classes

Database
DatabaseError
ItemDescriptor
NoSuchItemError
NoSuchResourceError
NoSuchSuiteError
NoSuchTestError
ResourceDescriptor
TestDescriptor

Functions

get_configuration_directory
get_configuration_file
get_database
is_database
load_database
set_path

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.setup-module.html0000664000076400007640000000734511122067145031023 0ustar stefanstefan qm.external.DocumentTemplate.setup
Package qm :: Package external :: Package DocumentTemplate :: Module setup
[hide private]
[frames] | no frames]

Module setup

source code

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.common-module.html0000664000076400007640000015446211122067145024064 0ustar stefanstefan qm.common
Package qm :: Module common
[hide private]
[frames] | no frames]

Module common

source code

Classes [hide private]
  QMException
An exception generated directly by QM.
  UserError
  PythonException
A 'PythonException' is a wrapper around a Python exception.
  RcConfiguration
Interface object to QM configuration files.
Functions [hide private]
 
get_lib_directory(*components)
Return the path to a file in the QM library directory.
source code
 
get_share_directory(*components)
Return the path to a file in the QM data file directory.
source code
 
get_doc_directory(*components)
Return a path to a file in the QM documentation file directory.
source code
 
format_exception(exc_info)
Format an exception as structured text.
source code
 
format_traceback(exc_info)
Format an exception traceback as structured text.
source code
 
convert_from_dos_text(text)
Replace CRLF with LF in 'text'.
source code
 
load_module(name, search_path=['/home/stefan/work/qmtest', '/usr/bin', '/home/stefan/work/qm..., load_path=['/home/stefan/work/qmtest', '/usr/bin', '/home/stefan/work/qm...)
Load a Python module.
source code
 
load_class(name, search_path=['/home/stefan/work/qmtest', '/usr/bin', '/home/stefan/work/qm..., load_path=['/home/stefan/work/qmtest', '/usr/bin', '/home/stefan/work/qm...)
Load a Python class.
source code
 
split_path_fully(path)
Split 'path' into components.
source code
 
open_temporary_file_fd(suffix='')
Create and open a temporary file.
source code
 
open_temporary_file(mode='w+b', suffix='')
Create and open a temporary file.
source code
 
close_file_on_exec(fd)
Prevent 'fd' from being inherited across 'exec'.
source code
 
copy(object)
Make a best-effort attempt to copy 'object'.
source code
 
wrap_lines(text, columns=72, break_delimiter='\\', indent='')
Wrap lines in 'text' to 'columns' columns.
source code
 
format_time(time_secs, local_time_zone=1)
Generate a text format representing a date and time.
source code
 
format_time_iso(time_secs=None)
Generate a ISO8601-compliant formatted date and time.
source code
 
parse_time_iso(time_string)
Parse a ISO8601-compliant formatted date and time.
source code
 
make_unique_tag()
Return a unique tag string.
source code
 
split_argument_list(command)
Split a command into an argument list.
source code
 
parse_boolean(value)
Parse a boolean string.
source code
 
parse_string_list(value)
Parse a string list.
source code
 
parse_time(time_string, default_local_time_zone=1)
Parse a date and/or time string.
source code
 
parse_assignment(assignment)
Parse an 'assignment' of the form 'name=value'.
source code
 
read_assignments(file)
Read assignments from a 'file'.
source code
 
get_username()
Returns the current username as a string.
source code
 
get_userid()
Returns the current user id as an integer.
source code
 
html_to_text(html, width=72)
Renders HTML to text in a simple way.
source code
Variables [hide private]
  program_name = None
The name of the application program.
  __load_module_lock = <_RLock(None, 0)>
A lock used by load_module.
  rc = RcConfiguration()
The configuration stored in system and user rc files.
  _unique_tag = 0
Function Details [hide private]

format_exception(exc_info)

source code 

Format an exception as structured text.

'exc_info' -- A three-element tuple containing exception info, of the form '(type, value, traceback)'.

returns -- A string containing a the formatted exception.

format_traceback(exc_info)

source code 

Format an exception traceback as structured text.

'exc_info' -- A three-element tuple containing exception info, of the form '(type, value, traceback)'.

returns -- A string containing a the formatted traceback.

load_module(name, search_path=['/home/stefan/work/qmtest', '/usr/bin', '/home/stefan/work/qm..., load_path=['/home/stefan/work/qmtest', '/usr/bin', '/home/stefan/work/qm...)

source code 

Load a Python module.

'name' -- The fully-qualified name of the module to load, for instance 'package.subpackage.module'.

'search_path' -- A sequence of directories. These directories are searched to find the module.

'load_path' -- The setting of 'sys.path' when the module is loaded.

returns -- A module object.

raises -- 'ImportError' if the module cannot be found.

load_class(name, search_path=['/home/stefan/work/qmtest', '/usr/bin', '/home/stefan/work/qm..., load_path=['/home/stefan/work/qmtest', '/usr/bin', '/home/stefan/work/qm...)

source code 

Load a Python class.

'name' -- The fully-qualified (including package and module names) class name, for instance 'package.subpackage.module.MyClass'. The class must be at the top level of the module's namespace, i.e. not nested in another class.

'search_path' -- A sequence of directories. These directories are searched to find the module.

'load_path' -- The setting of 'sys.path' when the module is loaded.

returns -- A class object.

raises -- 'ImportError' if the module containing the class can't be imported, or if there is no class with the specified name in that module, or if 'name' doesn't correspond to a class.

split_path_fully(path)

source code 

Split 'path' into components.

Uses 'os.path.split' recursively on the directory components of 'path' to separate all path components.

'path' -- The path to split.

returns -- A list of path componets.

open_temporary_file_fd(suffix='')

source code 

Create and open a temporary file.

'suffix' -- The last part of the temporary file name, as for Python's 'mktemp' function.

The file is open for reading and writing. The caller is responsible for deleting the file when finished with it.

returns -- A pair '(file_name, file_descriptor)' for the temporary file.

open_temporary_file(mode='w+b', suffix='')

source code 

Create and open a temporary file.

'mode' -- The mode argument to pass to 'fopen'.

'suffix' -- The last part of the temporary file name, as for Python's 'mktemp' function.

Like 'open_temporary_file_fd', except that the second element of the return value is a file object.

close_file_on_exec(fd)

source code 

Prevent 'fd' from being inherited across 'exec'.

'fd' -- A file descriptor, or object providing a 'fileno()' method.

This function has no effect on Windows.

copy(object)

source code 

Make a best-effort attempt to copy 'object'.

returns -- A copy of 'object', if feasible, or otherwise 'object'.

wrap_lines(text, columns=72, break_delimiter='\\', indent='')

source code 

Wrap lines in 'text' to 'columns' columns.

'text' -- The text to wrap.

'columns' -- The maximum number of columns of text.

'break_delimiter' -- Text to place at the end of each broken line (may be an empty string).

'indent' -- Text to place at the start of each line. The length of 'indent' does not count towards 'columns'.

returns -- The wrapped text.

format_time(time_secs, local_time_zone=1)

source code 

Generate a text format representing a date and time.

The output is in the format "YYYY-MM-DD HH:MM ZZZ".

'time_secs' -- The number of seconds since the start of the UNIX epoch, UTC.

'local_time_zone' -- If true, format the time in the local time zone. Otherwise, format it as UTC.

format_time_iso(time_secs=None)

source code 

Generate a ISO8601-compliant formatted date and time.

The output is in the format "YYYY-MM-DDThh:mm:ss+TZ", where TZ is a timezone specifier. We always normalize to UTC (and hence always use the special timezone specifier "Z"), to get proper sorting behaviour.

'time_secs' -- The time to be formatted, as returned by e.g. 'time.time()'. If 'None' (the default), uses the current time.

returns -- The formatted time as a string.

parse_time_iso(time_string)

source code 

Parse a ISO8601-compliant formatted date and time.

See also 'format_time_iso'.

'time_string' -- The string to be parsed, as returned by e.g. 'format_time_iso'.

returns -- The time as a float, like that returned by 'time.time'.

split_argument_list(command)

source code 

Split a command into an argument list.

'command' -- A string containing a shell or similar command.

returns -- An argument list obtained by splitting the command.

parse_boolean(value)

source code 

Parse a boolean string.

'value' -- A string.

returns -- True if 'value' is a true string, false if 'value' is a false string.

raises -- 'ValueError' if 'value' is neither a true string, nor a false string.

parse_string_list(value)

source code 

Parse a string list.

'value' -- A string.

returns -- A list of strings.

raises -- 'ValueError' if 'value' contains unbalanced quotes.

parse_time(time_string, default_local_time_zone=1)

source code 

Parse a date and/or time string.

'time_string' -- A string representing a date and time in the format returned by 'format_time'. This function makes a best-effort attempt to parse incomplete strings as well.

'default_local_time_zone' -- If the time zone is not specified in 'time_string' and this parameter is true, assume the time is in the local time zone. If this parameter is false, assume the time is UTC.

returns -- An integer number of seconds since the start of the UNIX epoch, UTC.

Only UTC and the current local time zone may be specified explicitly in 'time_string'.

parse_assignment(assignment)

source code 

Parse an 'assignment' of the form 'name=value'.

'aassignment' -- A string. The string should have the form 'name=value'.

returns -- A pair '(name, value)'.

read_assignments(file)

source code 

Read assignments from a 'file'.

'file' -- A file object containing the context. When the file is read, leading and trailing whitespace is discarded from each line in the file. Then, lines that begin with a '#' and lines that contain no characters are discarded. All other lines must be of the form 'NAME=VALUE' and indicate an assignment to the context variable 'NAME' of the indicated 'VALUE'.

returns -- A dictionary mapping each of the indicated 'NAME's to its corresponding 'VALUE'. If multiple assignments to the same 'NAME' are present, only the 'VALUE' from the last assignment is stored.

get_username()

source code 

Returns the current username as a string.

This is our best guess as to the username of the user who is actually logged in, as opposed to the effective user id used for running tests.

If the username cannot be found, raises a 'QMException'.

get_userid()

source code 

Returns the current user id as an integer.

This is the real user id, not the effective user id, to better track who is actually running the tests.

If the user id cannot be found or is not defined, raises a 'QMException'.

html_to_text(html, width=72)

source code 

Renders HTML to text in a simple way.

'html' -- A string containing the HTML code to be rendered.

'width' -- Column at which to word-wrap. Default 72.

returns -- A string containing a plain text rendering of the HTML.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.serial_target-module.html0000664000076400007640000001131411122067145030017 0ustar stefanstefan qm.test.classes.serial_target
Package qm :: Package test :: Package classes :: Module serial_target
[hide private]
[frames] | no frames]

Module serial_target

source code

Classes [hide private]
  SerialTarget
A target that runs tests in serial on the local machine.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.DirReportPage-class.html0000664000076400007640000004556211122067151027426 0ustar stefanstefan qm.test.web.web.DirReportPage
Package qm :: Package test :: Package web :: Module web :: Class DirReportPage
[hide private]
[frames] | no frames]

Class DirReportPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
    QMTestReportPage --+
                       |
                      DirReportPage

A run database directory page.

These attributes are available in DTML:

'path' -- The label directory that is being displayed.

'subdirs' -- A sequence of labels giving the subdirectories of this directory.

'test_ids' -- A sequence of labels giving the tests in this directory.

'suite_ids' -- A sequence of labels giving the suites in this directory.

'resource_ids' -- A sequence of labels giving the resources in this directory.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, path)
Construct a 'DirPage'.
source code
 
GetItems(self, kind=Result.TEST)
Return information about all of the items.
source code
 
MakeTestRunUrl(self, test_run)
Return the URL for navigating a particular test run.
source code

Inherited from QMTestReportPage: FormatTimeIso, GenerateHtmlHeader, GenerateStartBody, GetResultURL, GetRunDatabase

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]
  SORT_NAME = 'name'
Sort by name.
  SORT_OUTCOME = 'outcome'
Sort by outcome.
  SORT_EXPECTATION = 'expectation'
Sort by expectation.
  SORT_KINDS = [SORT_NAME, SORT_OUTCOME, SORT_EXPECTATION]
The kinds of sorting available.

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, path)
(Constructor)

source code 

Construct a 'DirPage'.

'server' -- The 'QMTestServer' creating this page.

'path' -- The label directory to display.

Overrides: web.DtmlPage.__init__

GetItems(self, kind=Result.TEST)

source code 

Return information about all of the items.

returns -- A sequence of 'Item' instances corresponding to all of the tests in this diretory.


Class Variable Details [hide private]

SORT_EXPECTATION

Sort by expectation. In other words, put unexpected outcomes before expected outcomes.

Value:
'expectation'

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate-pysrc.html0000664000076400007640000027000411122067152033160 0ustar stefanstefan qm.external.DocumentTemplate.pDocumentTemplate
Package qm :: Package external :: Package DocumentTemplate :: Module pDocumentTemplate
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.pDocumentTemplate

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  """Python implementations of document template some features 
 14   
 15   
 16  $Id: pDocumentTemplate.py 1069 2008-11-13 21:55:43Z stefan $""" 
 17  __version__='$Revision: 1069 $'[11:-2] 
 18   
 19  import string, sys, types 
 20  from string import join 
 21   
 22  StringType=type('') 
 23  TupleType=type(()) 
 24  isFunctionType={} 
 25  for name in ['BuiltinFunctionType', 'BuiltinMethodType', 'ClassType', 
 26               'FunctionType', 'LambdaType', 'MethodType', 'UnboundMethodType']: 
 27      try: isFunctionType[getattr(types,name)]=1 
 28      except: pass 
 29   
 30  try: # Add function and method types from Extension Classes 
 31      import ExtensionClass 
 32      isFunctionType[ExtensionClass.PythonMethodType]=1 
 33      isFunctionType[ExtensionClass.ExtensionMethodType]=1 
 34  except: pass 
 35   
 36  isFunctionType=isFunctionType.has_key 
 37   
 38  isSimpleType={} 
 39  for n in dir(types): 
 40      if (n[-4:]=='Type' and n != 'InstanceType' and 
 41          not isFunctionType(getattr(types, n))): 
 42          isSimpleType[getattr(types, n)]=1 
 43   
 44  isSimpleType=isSimpleType.has_key 
 45   
46 -class InstanceDict:
47 48 validate=None 49
50 - def __init__(self,o,namespace,validate=None):
51 self.self=o 52 self.cache={} 53 self.namespace=namespace 54 if validate is None: self.validate=namespace.validate 55 else: self.validate=validate
56
57 - def has_key(self,key):
58 return hasattr(self.self,key)
59
60 - def keys(self):
61 return self.self.__dict__.keys()
62
63 - def __repr__(self): return 'InstanceDict(%s)' % str(self.self)
64
65 - def __getitem__(self,key):
66 67 cache=self.cache 68 if cache.has_key(key): return cache[key] 69 70 inst=self.self 71 72 if key[:1]=='_': 73 if key != '__str__': 74 raise KeyError, key # Don't divuldge private data 75 r=str(inst) 76 else: 77 try: r=getattr(inst,key) 78 except AttributeError: raise KeyError, key 79 80 v=self.validate 81 if v is not None: v(inst,inst,key,r,self.namespace) 82 83 self.cache[key]=r 84 return r
85
86 -class MultiMapping:
87
88 - def __init__(self): self.dicts=[]
89
90 - def __getitem__(self, key):
91 for d in self.dicts: 92 try: return d[key] 93 except KeyError, AttributeError: pass 94 raise KeyError, key
95
96 - def push(self,d): self.dicts.insert(0,d)
97
98 - def pop(self, n=1):
99 r = self.dicts[-1] 100 del self.dicts[:n] 101 return r
102
103 - def keys(self):
104 kz = [] 105 for d in self.dicts: 106 kz = kz + d.keys() 107 return kz
108
109 -class DictInstance:
110
111 - def __init__(self, mapping):
112 self.__d=mapping
113
114 - def __getattr__(self, name):
115 try: return self.__d[name] 116 except KeyError: raise AttributeError, name
117
118 -class TemplateDict:
119 120 level=0 121
122 - def _pop(self, n=1): return self.dicts.pop(n)
123 - def _push(self, d): return self.dicts.push(d)
124
125 - def __init__(self):
126 m=self.dicts=MultiMapping() 127 self._pop=m.pop 128 self._push=m.push 129 try: self.keys=m.keys 130 except: pass
131
132 - def __getitem__(self,key,call=1, 133 simple=isSimpleType, 134 isFunctionType=isFunctionType, 135 ):
136 137 v = self.dicts[key] 138 if call: 139 if hasattr(v, '__render_with_namespace__'): 140 return v.__render_with_namespace__(self) 141 vbase = getattr(v, 'aq_base', v) 142 if callable(vbase): 143 if getattr(vbase, 'isDocTemp', None): 144 return v(None, self) 145 return v() 146 return v
147
148 - def has_key(self,key):
149 try: 150 v=self.dicts[key] 151 except KeyError: 152 return 0 153 return 1
154 155 getitem=__getitem__ 156
157 - def __call__(self, *args, **kw):
158 if args: 159 if len(args)==1 and not kw: 160 m=args[0] 161 else: 162 m=self.__class__() 163 for a in args: m._push(a) 164 if kw: m._push(kw) 165 else: m=kw 166 return (DictInstance(m),)
167
168 -def render_blocks(blocks, md):
169 rendered = [] 170 append=rendered.append 171 for section in blocks: 172 if type(section) is TupleType: 173 l=len(section) 174 if l==1: 175 # Simple var 176 section=section[0] 177 if type(section) is StringType: section=md[section] 178 else: section=section(md) 179 section=str(section) 180 else: 181 # if 182 cache={} 183 md._push(cache) 184 try: 185 i=0 186 m=l-1 187 while i < m: 188 cond=section[i] 189 if type(cond) is StringType: 190 n=cond 191 try: 192 cond=md[cond] 193 cache[n]=cond 194 except KeyError, v: 195 v=str(v) 196 if n != v: raise KeyError, v, sys.exc_traceback 197 cond=None 198 else: cond=cond(md) 199 if cond: 200 section=section[i+1] 201 if section: section=render_blocks(section,md) 202 else: section='' 203 m=0 204 break 205 i=i+2 206 if m: 207 if i==m: section=render_blocks(section[i],md) 208 else: section='' 209 210 finally: md._pop() 211 212 elif type(section) is not StringType: 213 section=section(md) 214 215 if section: rendered.append(section) 216 217 l=len(rendered) 218 if l==0: return '' 219 elif l==1: return rendered[0] 220 return join(rendered, '') 221 return rendered
222

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.xmlutil-module.html0000664000076400007640000006103411122067145024262 0ustar stefanstefan qm.xmlutil
Package qm :: Module xmlutil
[hide private]
[frames] | no frames]

Module xmlutil

source code

Functions [hide private]
 
make_public_id(name)
Return a public ID for the DTD with the given 'name'.
source code
 
make_system_id(name)
Return a system ID for the DTD with the given 'name'.
source code
 
load_xml_file(path)
Return a DOM document loaded from the XML file 'path'.
source code
 
load_xml(file)
Return a DOM document loaded from the XML file object 'file'.
source code
 
get_dom_text(node)
Return the text contained in DOM 'node'.
source code
 
child_tag_predicate(child_tag)
Return a predicate function for finding element nodes by tag.
source code
 
get_child(node, child_tag)
Return the child element node of 'node' whose tag is 'child_tag'.
source code
 
get_child_text(node, child_tag, default=None)
Return the text contained in a child of DOM 'node'.
source code
 
get_child_texts(node, child_tag)
Return a sequence of text contents of children.
source code
 
create_dom_text_element(document, tag, text)
Return a DOM element containing a single text node.
source code
 
create_dom_document(public_id, document_element_tag)
Create a DOM document.
source code
 
__hyphen_replacement(match) source code
 
sanitize_text_for_comment(text)
Return 'text' modified so that it is valid for an XML comment.
source code
Variables [hide private]
  __dom_implementation = xml.dom.minidom.getDOMImplementation()
  __hyphen_regex = re.compile(r'(--+)')
Function Details [hide private]

make_public_id(name)

source code 

Return a public ID for the DTD with the given 'name'.

'name' -- The name of the DTD.

returns -- A public ID for the DTD.

make_system_id(name)

source code 

Return a system ID for the DTD with the given 'name'.

'name' -- The name of the DTD, as a relative UNIX path.

returns -- A URL for the DTD.

load_xml(file)

source code 

Return a DOM document loaded from the XML file object 'file'.

'file' -- A file object, opened for reading.

returns -- The DOM document contained in 'file'.

This function closes 'file', whether or not reading the document was successful.

get_dom_text(node)

source code 

Return the text contained in DOM 'node'.

'node' -- A DOM element node.

prerequisites -- 'node' is an element node with exactly one child, which is a text node.

child_tag_predicate(child_tag)

source code 

Return a predicate function for finding element nodes by tag.

returns -- A predicate function that takes a node as its argument and returns true if the node is an element node whose tag is 'child_tag'.

get_child(node, child_tag)

source code 

Return the child element node of 'node' whose tag is 'child_tag'.

'node' -- A DOM node. It must have exactly one element child with the tag 'child_tag'.

'child_tag' -- The desired element tag.

returns -- A child DOM node of 'node'.

raises -- 'KeyError' if 'node' has no element child with tag 'child_tag', or more than one..

get_child_text(node, child_tag, default=None)

source code 

Return the text contained in a child of DOM 'node'.

'child_tag' -- The tag of the child node whose text is to be retrieved.

'default' -- If 'node' has no child element with tag 'child_tag', returns 'default', unless 'default' is 'None'.

raises -- 'KeyError' if 'default' is 'None' and 'node' has no child element with tag 'child_tag'.

get_child_texts(node, child_tag)

source code 

Return a sequence of text contents of children.

'node' -- A DOM node.

returns -- The list containing all child nodes of 'node' which have tag 'child_tag'. Each child must have exactly one child of its own, which must be a text node.

create_dom_text_element(document, tag, text)

source code 

Return a DOM element containing a single text node.

'document' -- The containing DOM document.

'tag' -- The element tag.

'text' -- The text contents of the text node.

create_dom_document(public_id, document_element_tag)

source code 

Create a DOM document.

'public_id' -- The (partial) public ID for the DTD.

'document_element_tag' -- The tag of the main document element.

returns -- A DOM document node.


qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-I.html0000664000076400007640000004662211122067144024307 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

I



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.file.FileContentsTest-class.html0000664000076400007640000005021311122067147031170 0ustar stefanstefan qm.test.classes.file.FileContentsTest
Package qm :: Package test :: Package classes :: Module file :: Class FileContentsTest
[hide private]
[frames] | no frames]

Class FileContentsTest

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
                  test.Test --+
                              |
                             FileContentsTest

Check that the contents of a file match the expected value.

A 'FileContentsTest' examines the contents of a file. The test passes if and only if the contents exactly match the expected value.

The path to the file itself is not specified explicitly in the test. Instead, it is taken from a contex property; the name of that variable is specified in the **Path Property** field.

Optionally, the test may specify one or more substitutions. Each substitution consists of a regular expression pattern and a replacement string. Both the actual file contents and the expected file contents are processed with these substitutions, with all pattern matches replaced with the corresponding substitutions, before the comparison is performed.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code
 
__PerformSubstitutions(self, text)
Perform substitutions on a body of text.
source code

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "path_property", title=...
A list of the arguments to the extension class.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

Overrides: test.Test.Run
(inherited documentation)

__PerformSubstitutions(self, text)

source code 

Perform substitutions on a body of text.

returns -- The string 'text', processed with the substitutions configured for this test instance.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "path_property", title= "Path Property", de\
scription= """The context property naming the file.

            The context property given here will contain the path name
            of the file.""", not_empty_text= 1, default_value= "path")\
, qm.fields.TextField(name= "expected_contents", title= "Expected Cont\
ents", description= """The expected contents of the file.""", verbatim\
= "true", multiline= "true", default_value= ""), qm.fields.SetField(Su\
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result_stream-module.html0000664000076400007640000001112111122067145026423 0ustar stefanstefan qm.test.result_stream
Package qm :: Package test :: Module result_stream
[hide private]
[frames] | no frames]

Module result_stream

source code

Classes [hide private]
  ResultStream
A 'ResultStream' displays test results.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.tet_stream.TETStream-class.html0000664000076400007640000011744111122067147031002 0ustar stefanstefan qm.test.classes.tet_stream.TETStream
Package qm :: Package test :: Package classes :: Module tet_stream :: Class TETStream
[hide private]
[frames] | no frames]

Class TETStream

source code

                 object --+            
                          |            
        extension.Extension --+        
                              |        
     result_stream.ResultStream --+    
                                  |    
file_result_stream.FileResultStream --+
                                      |
                                     TETStream

A 'TETStream' formats results as a TET journal.

Provides special handling for 'DejaGNUTest' results.

TET: http://tetworks.opengroup.org/
TET journal format: see appendix C and D of
   http://tetworks.opengroup.org/documents/3.7/uguide.pdf

For the meaning of TET result codes, we use as guidelines the LSB
test faq, question Q1.11:
    * PASS - a test result belonging to this group is considered to
      be a pass for compliance testing purposes:
          o Pass - the test has been executed correctly and to
            completion without any kind of problem
          o Warning - the functionality is acceptable, but you
            should be aware that later revisions of the relevant
            standards or specification may change the requirements
            in this area.
          o FIP - additional information is provided which needs to
            be checked manually.
          o Unsupported - an optional feature is not available or
            not supported in the implementation under test.
          o Not in Use - some tests may not be required in certain
            test modes or when an interface can be implemented by a
            macro or function and there are two versions of the test
            only one is used.
          o Untested - no test written to check a particular feature
            or an optional facility needed to perform a test is not
            available on the system.
      [There are also "notimp" and "unapproved" cases mentioned in
      the LSB-FHS README, but they are otherwise undocumented, and
      don't correspond to any DejaGNU or QMTest outcomes anyway.]
    * FAIL - a test result belonging to this group is considered to
      be a fail for compliance testing purposes (unless the failure
      has been waived by an agreed Problem Report in the
      Certification Problem Reporting database):
          o Fail - the interface did not behave as expected.
          o Uninitiated - the particular test in question did not
            start to execute.
          o Unresolved - the test started but did not reach the
            point where the test was able to report success or
            failure.
          o Unreported - a major error occurred during the testset
            execution.  (The TET manual calls this NORESULT.)
(From http://www.linuxbase.org/test/lsb-runtime-test-faq.html )

DejaGNU test results are described as:
    * PASS - A test has succeeded.
    * FAIL - A test has produced the bug it was intended to
      capture.
    * WARNING - Declares detection of a minor error in the test case
      itself.  Use WARNING rather than ERROR for cases (such as
      communication failure to be followed by a retry) where the
      test case can recover from the error.  Note that sufficient
      warnings will cause a test to go from PASS/FAIL to
      UNRESOLVED.
    * ERROR - Declares a severe error in the testing framework
      itself.  An ERROR also causes a test to go from PASS/FAIL to
      UNRESOLVED.
    * UNRESOLVED - A test produced indeterminate results.  Usually,
      this means the test executed in an unexpected fashion; this
      outcome requires that a human being go over results, to
      determine if the test should have passed or failed.  This
      message is also used for any test that requires human
      intervention because it is beyond the abilities of the testing
      framework.  Any unresolved test should be resolved to PASS or
      FAIL before a test run can be considered finished.

      Examples:
          - a test's execution is interrupted
          - a test does not produce a clear result (because of
            WARNING or ERROR messages)
          - a test depends on a previous test case which failed
    * UNTESTED - a test case that isn't run for some technical
      reason.  (E.g., a dummy test created as a placeholder for a
      test that is not yet written.)
    * UNSUPPORTED - Declares that a test case depends on some
      facility that does not exist in the testing environment; the
      test is simply meaningless.
(From a combination of DejaGNU manual sections "Core Internal
Procedures", "C Unit Testing API", and "A POSIX conforming test
framework".)

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code
 
_WriteLine(self, code, data, comment)
Write a line in TET journal format.
source code
 
_IsDejaGNUResult(self, result)
Returns 'True' if 'result' has DejaGNU subtests.
source code
 
_TETFormatTime(self, time_string)
Converts an ISO-format date-time to a TET-format date-time.
source code
 
_ExtractTime(self, result, key)
Extracts the start time from a result.
source code
 
WriteAnnotation(self, key, value)
Output an annotation for this run.
source code
 
_WriteInitialStuff(self)
Print TET header information, but only on first call.
source code
 
WriteResult(self, result)
Output a test result.
source code
 
_WriteTCStart(self, result)
Write a TET test case start line.
source code
 
_WriteResultAnnotations(self, result, purpose, num_restrict=None, seq_start=1)
Writes out annotations for a 'result' in TET format.
source code
 
_WriteDejaGNUResult(self, result)
Write out a result that has DejaGNU subtest information.
source code
 
_WriteTestResult(self, result)
Write out a result that does not have DejaGNU annotations.
source code
 
_WriteResourceResult(self, result)
Write out information on a resource result.
source code
 
Summarize(self)
Output summary information about the results.
source code

Inherited from result_stream.ResultStream: WriteAllAnnotations

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  PASS = 0, "PASS"
  WARNING = 101, "WARNING"
  FIP = 102, "FIP"
  UNSUPPORTED = 4, "UNSUPPORTED"
  NOTINUSE = 3, "NOTINUSE"
  UNTESTED = 5, "UNTESTED"
  FAIL = 1, "FAIL"
  UNINITIATED = 6, "UNINITIATED"
  UNRESOLVED = 2, "UNRESOLVED"
  UNREPORTED = 7, "UNREPORTED"

Inherited from file_result_stream.FileResultStream: arguments, file, filename

Inherited from result_stream.ResultStream: expected_outcomes, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

_TETFormatTime(self, time_string)

source code 

Converts an ISO-format date-time to a TET-format date-time.

returns -- A 2-tuple whose first element is the time as a string, and whose second is the date as a string.

WriteAnnotation(self, key, value)

source code 

Output an annotation for this run.

Subclasses should override this if they want to store/display annotations; the default implementation simply discards them.

'key' -- the key value as a string.

'value' -- the value of this annotation as a string.

Overrides: result_stream.ResultStream.WriteAnnotation
(inherited documentation)

_WriteInitialStuff(self)

source code 

Print TET header information, but only on first call.

Second and later calls are no-ops.

WriteResult(self, result)

source code 

Output a test result.

Subclasses must override this method; the default implementation raises a 'NotImplementedError'.

'result' -- A 'Result'.

Overrides: result_stream.ResultStream.WriteResult
(inherited documentation)

_WriteResultAnnotations(self, result, purpose, num_restrict=None, seq_start=1)

source code 

Writes out annotations for a 'result' in TET format.

Annotations are represented as (sequences of) "test case information" lines.

'result' -- The 'Result' whose annotations should be written.

'num_restrict' -- Only write out annotations that end with this number. If the number is '1', also writes out all results that don't end in any number, with "INFO: " prefixed. If 'None', writes out all annotations.

'seq_start' -- The TET test case information sequence number to start with.

_WriteResourceResult(self, result)

source code 

Write out information on a resource result.

TET has no concept of resources, so we ignore successful resources, and print out "test case controller messages" for ERRORs and FAILUREs.

Summarize(self)

source code 

Output summary information about the results.

When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point.

Derived class methods may override this method. They should, however, invoke this version before returning.

Overrides: result_stream.ResultStream.Summarize
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.context-pysrc.html0000664000076400007640000036605011122067154025107 0ustar stefanstefan qm.test.context
Package qm :: Package test :: Module context
[hide private]
[frames] | no frames]

Source Code for Module qm.test.context

  1  ######################################################################## 
  2  # 
  3  # File:   context.py 
  4  # Author: Mark Mitchell 
  5  # Date:   11/06/2001 
  6  # 
  7  # Contents: 
  8  #   QMTest Context class 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ######################################################################## 
 17   
 18  import qm 
 19  import qm.common 
 20  import re 
 21  import sys 
 22  import types 
 23   
 24  ######################################################################## 
 25  # Classes 
 26  ######################################################################## 
 27   
28 -class ContextException(qm.common.QMException):
29 """A 'ContextException' indicates an invalid context variable.""" 30
31 - def __init__(self, key, msg = "missing context variable"):
32 """Construct a new 'ContextException'. 33 34 'key' -- A string giving the context key for which no valid 35 value was available. 36 37 'msg' -- A diagnostic identifier explaining the problem. The 38 message string may contain a fill-in for the key.""" 39 40 msg = qm.error(msg, key = key) 41 qm.common.QMException.__init__(self, msg) 42 self.key = key
43 44 45
46 -class ContextWrapper:
47 """Do-nothing class to preserve pickle compatability. 48 49 A class called 'ContextWrapper' used to be used in instead of a 50 'Context' class in some cases, and we used to put contexts into 51 'Result's. Because of how pickles work, this means that the only way 52 to unpickle these old 'Result's is to have a do-nothing placeholder 53 class that can be instantiated and then thrown away.""" 54 55 pass
56 57 58
59 -class Context(types.DictType):
60 """Test-time and local configuration for tests. 61 62 A 'Context' object contains all of the information a test needs to 63 execute, beyond what is stored as part of the test specification 64 itself. Information in the context can include, 65 66 * Local (per-user, etc.) configuration, such as where to find the 67 tested program. 68 69 * Environmental information, such as which machine the test is 70 running on. 71 72 * One-time configuration, including test arguments specified on 73 the command line. 74 75 A 'Context' object is effectively a mapping object whose keys must 76 be labels and values must be strings.""" 77 78 TARGET_CONTEXT_PROPERTY = "qmtest.target" 79 """The context variable giving the name of the current target.""" 80 81 DB_PATH_CONTEXT_PROPERTY = "qmtest.dbpath" 82 """The context variable giving the path to the database. 83 84 The value of this context variable will be a string giving the 85 path to the database directory. For example, if QMTest is invoked 86 as 'qmtest -D /path/to/db run', the value of this variable would 87 be '/path/to/db'. The value may be an absolute or a relative 88 path.""" 89 90 ID_CONTEXT_PROPERTY = "qmtest.id" 91 """The context variable giving the name of the running test or resource. 92 93 This value of this context variable will be the string giving the 94 name of the of the test or resource that is presently executing.""" 95 96 TMPDIR_CONTEXT_PROPERTY = "qmtest.tmpdir" 97 """A context property whose value is a string giving the path to a 98 temporary directory. This directory will be used only by the 99 'Runnable' in whose context this property occurs during the 100 execution of that 'Runnable'. No other object will use the same 101 temporary directory at the same time. There is no guarantee that 102 the temporary directory is empty, however; it may contain files 103 left behind by the execution of other 'Runnable' objects.""" 104 105 __safe_for_unpickling__ = 1 106 """Required to unpickle new-style classes under Python 2.2.""" 107
108 - def __init__(self, context = None):
109 """Construct a new context. 110 111 'context' -- If not 'None', the existing 'Context' being 112 wrapped by this new context.""" 113 114 super(Context, self).__init__() 115 116 self.__context = context 117 118 # Stuff everything in the RC configuration into the context. 119 options = qm.rc.GetOptions() 120 for option in options: 121 value = qm.rc.Get(option, None) 122 assert value is not None 123 self[option] = value
124 125
126 - def GetDerivedValue(self, klass, variable, default = None):
127 """Return the value for 'variable' in scope 'klass'. 128 Scopes are nested with '.', and inner variables hide 129 outer variables of the same name. Thus, looking up the 130 value of 'a.b.c.var' will return 1 if the context 131 contains 132 a.b.c.var=1 133 but 2 if it contains 134 a.b.d.var=1 135 a.b.var=2 136 a.var=3. 137 138 'klass' -- The variable's scope. 139 140 'variable' -- The variable name. 141 142 'default' -- Default value.""" 143 144 145 while True: 146 147 if klass: 148 k = klass + '.' + variable 149 else: 150 k = variable 151 if self.has_key(k): 152 return self[k] 153 if not klass: 154 return default 155 if '.' not in klass: 156 klass = '' 157 else: 158 klass = klass[0:klass.rfind('.')]
159 160
161 - def GetBoolean(self, key, default = None):
162 """Return the boolean value associated with 'key'. 163 164 'key' -- A string. 165 166 'default' -- A default boolean value. 167 168 returns -- The value associated with 'key' in the context, 169 interpreted as a boolean. 170 171 If there is no value associated with 'key' and default is not 172 'None', then the boolean value associated with default is 173 used. If there is no value associated with 'key' and default 174 is 'None', an exception is raised. 175 176 The value associated with 'key' must be a string. If not, an 177 exception is raised. If the value is a string, but does not 178 correspond to a boolean value, an exception is raised.""" 179 180 valstr = self.get(key) 181 if valstr is None: 182 if default is None: 183 raise ContextException(key) 184 else: 185 return default 186 187 try: 188 return qm.common.parse_boolean(valstr) 189 except ValueError: 190 raise ContextException(key, "invalid boolean context var")
191 192
193 - def GetStringList(self, key, default = None):
194 """Return the list of strings associated with 'key'. 195 196 'key' -- A string. 197 198 'default' -- A default list. 199 200 If there is no value associated with 'key' and default is not 201 'None', then the boolean value associated with default is 202 used. If there is no value associated with 'key' and default 203 is 'None', an exception is raised. 204 205 The value associated with 'key' must be a string. If not, an 206 exception is raised. If the value is a string, but does not 207 correspond to a string list, an exception is raised. 208 """ 209 210 valstr = self.get(key) 211 if valstr is None: 212 if default is None: 213 raise ContextException(key) 214 else: 215 return default 216 217 try: 218 return qm.common.parse_string_list(valstr) 219 except ValueError: 220 raise ContextException(key, "invalid string list context var")
221 222
223 - def GetTemporaryDirectory(self):
224 """Return the path to the a temporary directory. 225 226 returns -- The path to the a temporary directory. The 227 'Runnable' object may make free use of this temporary 228 directory; no other 'Runnable's will use the same directory at 229 the same time.""" 230 231 return self[self.TMPDIR_CONTEXT_PROPERTY]
232 233
234 - def Read(self, file_name):
235 """Read the context file 'file_name'. 236 237 'file_name' -- The name of the context file. 238 239 Reads the context file and adds the context properties in the 240 file to 'self'.""" 241 242 if file_name == "-": 243 # Read from standard input. 244 file = sys.stdin 245 else: 246 # Read from a named file. 247 try: 248 file = open(file_name, "r") 249 except: 250 raise qm.cmdline.CommandError, \ 251 qm.error("could not read file", path=file_name) 252 # Read the assignments. 253 assignments = qm.common.read_assignments(file) 254 # Add them to the context. 255 for (name, value) in assignments.items(): 256 try: 257 # Insert it into the context. 258 self[name] = value 259 except ValueError, msg: 260 # The format of the context key is invalid, but 261 # raise a 'CommandError' instead. 262 raise qm.cmdline.CommandError, msg
263 264 265 # Methods to simulate a map object. 266
267 - def __contains__(self, key):
268 269 if super(Context, self).__contains__(key): 270 return 1 271 272 if self.__context is not None: 273 return self.__context.__contains__(key) 274 275 return 0
276 277
278 - def get(self, key, default = None):
279 280 if key in self: 281 return self[key] 282 283 return default
284 285
286 - def has_key(self, key):
287 288 return key in self
289 290
291 - def __getitem__(self, key):
292 try: 293 return super(Context, self).__getitem__(key) 294 except KeyError: 295 if self.__context is None: 296 raise ContextException(key) 297 try: 298 return self.__context[key] 299 except KeyError: 300 raise ContextException(key)
301 302
303 - def items(self):
304 305 if self.__context is None: 306 return super(Context, self).items() 307 else: 308 # Have to be careful, because self.__context and self may 309 # contain different values for the same keys, and the values 310 # defined in self should override the values defined in 311 # self.__context. 312 unified_dict = dict(self.__context.items()) 313 unified_dict.update(self) 314 return unified_dict.items()
315 316 317 # Helper methods. 318
319 - def GetAddedProperties(self):
320 """Return the properties added to this context by resources. 321 322 returns -- A map from strings to values indicating properties 323 that were added to this context by resources.""" 324 325 if self.__context is None: 326 return {} 327 328 added = self.__context.GetAddedProperties() 329 added.update(self) 330 return added
331

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.Authenticator-class.html0000664000076400007640000002122011122067151026161 0ustar stefanstefan qm.user.Authenticator
qm :: user :: Authenticator :: Class Authenticator
[hide private]
[frames] | no frames]

Class Authenticator

source code

Known Subclasses:

Base class for authentication classes.

An 'Authenticator' object is responsible for determining the authenticity of a user. The inputs to an authentication action depend on the mechanism with which the user communicates with the program -- for instance, a web request, command invocation, or email message.

Instance Methods [hide private]
 
AuthenticateDefaultUser(self)
Authenticate for the default user, if one is provided.
source code
 
AuthenticateWebRequest(self, request)
Authenticate a login web request.
source code
Method Details [hide private]

AuthenticateDefaultUser(self)

source code 

Authenticate for the default user, if one is provided.

returns -- The user ID of the default user.

AuthenticateWebRequest(self, request)

source code 

Authenticate a login web request.

'request' -- A web request containing the user's login information.

returns -- The user ID of the authenticated user.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.target-pysrc.html0000664000076400007640000055513211122067162024711 0ustar stefanstefan qm.test.target
Package qm :: Package test :: Module target
[hide private]
[frames] | no frames]

Source Code for Module qm.test.target

  1  ######################################################################## 
  2  # 
  3  # File:   target.py 
  4  # Author: Mark Mitchell 
  5  # Date:   10/29/2001 
  6  # 
  7  # Contents: 
  8  #   QMTest Target class. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  import qm.common 
 22  import qm.extension 
 23  import qm.platform 
 24  import qm.test.base 
 25  from   qm.test.context import * 
 26  from   qm.test.result import * 
 27  from   qm.test.database import NoSuchResourceError 
 28  import re 
 29  import signal 
 30  import sys 
 31   
 32  ######################################################################## 
 33  # classes 
 34  ######################################################################## 
 35   
36 -class Target(qm.extension.Extension):
37 """Base class for target implementations. 38 39 A 'Target' is an entity that can run tests. QMTest can spread the 40 workload from multiple tests across multiple targets. In 41 addition, a single target can run more than one test at once. 42 43 'Target' is an abstract class. 44 45 You can extend QMTest by providing your own target class 46 implementation. 47 48 To create your own target class, you must create a Python class 49 derived (directly or indirectly) from 'Target'. The documentation 50 for each method of 'Target' indicates whether you must override it 51 in your target class implementation. Some methods may be 52 overridden, but do not need to be. You might want to override 53 such a method to provide a more efficient implementation, but 54 QMTest will work fine if you just use the default version.""" 55 56 arguments = [ 57 qm.fields.TextField( 58 name="name", 59 title="Name", 60 description="""The name of this target. 61 62 The name of the target. The target name will be recorded 63 in any tests executed on that target so that you can see 64 where the test was run.""", 65 default_value=""), 66 qm.fields.TextField( 67 name="group", 68 title="Group", 69 description="""The group associated with this target. 70 71 Some tests may only be able to run on some targets. A 72 test can specify a pattern indicating the set of targets 73 on which it will run.""", 74 default_value="") 75 ] 76 77 kind = "target" 78
79 - class __ResourceSetUpException(Exception):
80 """An exception indicating that a resource could not be set up.""" 81
82 - def __init__(self, resource):
83 """Construct a new 'ResourceSetUpException'. 84 85 'resource' -- The name of the resoure that could not be 86 set up.""" 87 88 self.resource = resource
89 90 91
92 - def __init__(self, database, arguments = None, **args):
93 """Construct a 'Target'. 94 95 'database' -- The 'Database' containing the tests that will be 96 run. 97 98 'arguments' -- As for 'Extension.__init__'. 99 100 'args' -- As for 'Extension.__init__'.""" 101 102 if arguments: args.update(arguments) 103 super(Target, self).__init__(**args) 104 105 self.__database = database
106 107
108 - def GetName(self):
109 """Return the name of the target. 110 111 Derived classes must not override this method.""" 112 113 return self.name
114 115
116 - def GetGroup(self):
117 """Return the group of which the target is a member. 118 119 Derived classes must not override this method.""" 120 121 return self.group
122 123
124 - def GetDatabase(self):
125 """Return the 'Database' containing the tests this target will run. 126 127 returns -- The 'Database' containing the tests this target will 128 run. 129 130 Derived classes must not override this method.""" 131 132 return self.__database
133 134
135 - def IsIdle(self):
136 """Return true if the target is idle. 137 138 returns -- True if the target is idle. If the target is idle, 139 additional tasks may be assigned to it. 140 141 Derived classes must override this method.""" 142 143 raise NotImplementedError
144 145
146 - def IsInGroup(self, group_pattern):
147 """Returns true if this 'Target' is in a particular group. 148 149 'group_pattern' -- A string giving a regular expression. 150 151 returns -- Returns true if the 'group_pattern' denotes a 152 regular expression that matches the group for this 'Target', 153 false otherwise.""" 154 155 return re.match(group_pattern, self.GetGroup())
156 157
158 - def Start(self, response_queue, engine=None):
159 """Start the target. 160 161 'response_queue' -- The 'Queue' in which the results of test 162 executions are placed. 163 164 'engine' -- The 'ExecutionEngine' that is starting the target, 165 or 'None' if this target is being started without an 166 'ExecutionEngine'. 167 168 Derived classes may override this method, but the overriding 169 method must call this method at some point during its 170 execution.""" 171 172 self.__response_queue = response_queue 173 self.__engine = engine 174 # There are no resources available on this target yet. 175 self.__resources = {} 176 self.__order_of_resources = []
177 178
179 - def Stop(self):
180 """Stop the target. 181 182 Clean up all resources that have been set up on this target 183 and take whatever other actions are required to stop the 184 target. 185 186 Derived classes may override this method.""" 187 188 # Clean up any available resources. 189 self.__order_of_resources.reverse() 190 for name in self.__order_of_resources: 191 rop = self.__resources[name] 192 if rop and rop[1] == Result.PASS: 193 self._CleanUpResource(name, rop[0]) 194 del self.__response_queue 195 del self.__engine 196 del self.__resources 197 del self.__order_of_resources
198 199
200 - def RunTest(self, descriptor, context):
201 """Run the test given by 'test_id'. 202 203 'descriptor' -- The 'TestDescriptor' for the test. 204 205 'context' -- The 'Context' in which to run the test. 206 207 Derived classes may override this method.""" 208 209 # Create the result. 210 result = Result(Result.TEST, descriptor.GetId()) 211 try: 212 # Augment the context appropriately. 213 context = Context(context) 214 context[context.TARGET_CONTEXT_PROPERTY] = self.GetName() 215 context[context.TMPDIR_CONTEXT_PROPERTY] \ 216 = self._GetTemporaryDirectory() 217 context[context.DB_PATH_CONTEXT_PROPERTY] \ 218 = descriptor.GetDatabase().GetPath() 219 # Set up any required resources. 220 self.__SetUpResources(descriptor, context) 221 # Make the ID of the test available. 222 context[context.ID_CONTEXT_PROPERTY] = descriptor.GetId() 223 # Note the start time. 224 result[Result.START_TIME] = qm.common.format_time_iso() 225 # Run the test. 226 try: 227 descriptor.Run(context, result) 228 finally: 229 # Note the end time. 230 result[Result.END_TIME] = qm.common.format_time_iso() 231 except KeyboardInterrupt: 232 result.NoteException(cause = "Interrupted by user.") 233 # We received a KeyboardInterrupt, indicating that the 234 # user would like to exit QMTest. Ask the execution 235 # engine to stop. 236 if self.__engine: 237 self.__engine.RequestTermination() 238 except qm.platform.SignalException, e: 239 # Note the exception. 240 result.NoteException(cause = str(e)) 241 # If we get a SIGTERM, propagate it so that QMTest 242 # terminates. 243 if e.GetSignalNumber() == signal.SIGTERM: 244 # Record the result so that the traceback is 245 # available. 246 self._RecordResult(result) 247 # Ask the execution engine to stop running tests. 248 if self.__engine: 249 self.__engine.RequestTermination() 250 # Re-raise the exception. 251 raise 252 except self.__ResourceSetUpException, e: 253 result.SetOutcome(Result.UNTESTED) 254 result[Result.CAUSE] = qm.message("failed resource") 255 result[Result.RESOURCE] = e.resource 256 except: 257 result.NoteException() 258 # Record the result. 259 self._RecordResult(result)
260 261
262 - def _RecordResult(self, result):
263 """Record the 'result'. 264 265 'result' -- A 'Result' of a test or resource execution. 266 267 Derived classes may override this method, but the overriding 268 method must call this method at some point during its 269 execution.""" 270 271 # Record the target in the result. 272 result[Result.TARGET] = self.GetName() 273 # Put the result into the response queue. 274 self.__response_queue.put(result)
275 276
277 - def _BeginResourceSetUp(self, resource_name):
278 """Begin setting up the indicated resource. 279 280 'resource_name' -- A string naming a resource. 281 282 returns -- If at attempt to set up the resource has already 283 been made, returns a tuple '(resource, outcome, properties)'. 284 The 'resource' is the 'Resource' object itself, but may be 285 'None' if the resource could not be set up. The 'outcome' 286 indicates the outcome that resulted when the resource was set 287 up. The 'properties' are a map from strings to strings 288 indicating properties added by this resource. 289 290 If the resource has not been set up, but _BeginResourceSetUp 291 has already been called for the resource, then the contents of 292 the tuple will all be 'None'. 293 294 If this is the first time _BeginResourceSetUp has been called 295 for this resource, then 'None' is returned, but the resource 296 is marked as in the process of being set up. It is the 297 caller's responsibility to finish setting it up by calling 298 '_FinishResourceSetUp'.""" 299 300 rop = self.__resources.get(resource_name) 301 if rop: 302 return rop 303 self.__resources[resource_name] = (None, None, None) 304 return None
305 306
307 - def _FinishResourceSetUp(self, resource, result, properties):
308 """Finish setting up a resource. 309 310 'resource' -- The 'Resource' itself. 311 312 'result' -- The 'Result' associated with setting up the 313 resource. 314 315 'properties' -- A dictionary of additional context properties 316 that should be provided to tests that depend on this resource. 317 318 returns -- A tuple of the same form as is returned by 319 '_BeginResourceSetUp' when the resource has already been set 320 up.""" 321 322 # The temporary directory is not be preserved; there is no 323 # guarantee that it will be the same in a test that depends on 324 # this resource as it was in the resource itself. 325 del properties[Context.TMPDIR_CONTEXT_PROPERTY] 326 rop = (resource, result.GetOutcome(), properties) 327 self.__resources[result.GetId()] = rop 328 self.__order_of_resources.append(result.GetId()) 329 return rop
330 331
332 - def __SetUpResources(self, descriptor, context):
333 """Set up all the resources associated with 'descriptor'. 334 335 'descriptor' -- The 'TestDescriptor' or 'ResourceDescriptor' 336 indicating the test or resource that is about to be run. 337 338 'context' -- The 'Context' in which the resources will be 339 executed. 340 341 returns -- A tuple of the same form as is returned by 342 '_BeginResourceSetUp' when the resource has already been set 343 up.""" 344 345 # See if there are resources that need to be set up. 346 for resource in descriptor.GetResources(): 347 (r, outcome, resource_properties) \ 348 = self._SetUpResource(resource, context) 349 350 # If the resource was not set up successfully, 351 # indicate that the test itself could not be run. 352 if outcome != Result.PASS: 353 raise self.__ResourceSetUpException, resource 354 # Update the list of additional context properties. 355 context.update(resource_properties) 356 357 return context
358 359
360 - def _SetUpResource(self, resource_name, context):
361 """Set up the resource given by 'resource_id'. 362 363 'resource_name' -- The name of the resource to be set up. 364 365 'context' -- The 'Context' in which to run the resource. 366 367 returns -- A map from strings to strings indicating additional 368 properties added by this resource.""" 369 370 # Begin setting up the resource. 371 rop = self._BeginResourceSetUp(resource_name) 372 # If it has already been set up, there is no need to do it 373 # again. 374 if rop: 375 return rop 376 # Set up the context. 377 wrapper = Context(context) 378 result = Result(Result.RESOURCE_SETUP, resource_name, Result.PASS) 379 resource = None 380 # Get the resource descriptor. 381 try: 382 resource_desc = self.GetDatabase().GetResource(resource_name) 383 # Set up the resources on which this resource depends. 384 self.__SetUpResources(resource_desc, wrapper) 385 # Make the ID of the resource available. 386 wrapper[Context.ID_CONTEXT_PROPERTY] = resource_name 387 # Set up the resource itself. 388 try: 389 resource_desc.SetUp(wrapper, result) 390 finally: 391 del wrapper[Context.ID_CONTEXT_PROPERTY] 392 # Obtain the resource within the try-block so that if it 393 # cannot be obtained the exception is handled below. 394 resource = resource_desc.GetItem() 395 except self.__ResourceSetUpException, e: 396 result.Fail(qm.message("failed resource"), 397 { result.RESOURCE : e.resource }) 398 except NoSuchResourceError: 399 result.NoteException(cause="Resource is missing from the database.") 400 self._RecordResult(result) 401 return (None, result, None) 402 except qm.test.base.CouldNotLoadExtensionError, e: 403 result.NoteException(e.exc_info, 404 cause = "Could not load extension class") 405 except KeyboardInterrupt: 406 result.NoteException() 407 # We received a KeyboardInterrupt, indicating that the 408 # user would like to exit QMTest. Ask the execution 409 # engine to stop. 410 if self.__engine: 411 self.__engine.RequestTermination() 412 except: 413 result.NoteException() 414 # Record the result. 415 self._RecordResult(result) 416 # And update the table of available resources. 417 return self._FinishResourceSetUp(resource, result, 418 wrapper.GetAddedProperties())
419 420
421 - def _CleanUpResource(self, name, resource):
422 """Clean up the 'resource'. 423 424 'resource' -- The 'Resource' that should be cleaned up. 425 426 'name' -- The name of the resource itself.""" 427 428 result = Result(Result.RESOURCE_CLEANUP, name) 429 # Clean up the resource. 430 try: 431 val = resource.CleanUp(result) 432 except: 433 result.NoteException() 434 self._RecordResult(result)
435 436
437 - def _GetTemporaryDirectory(self):
438 """Return the path to a temporary directory. 439 440 returns -- The path to a temporary directory to pass along to 441 tests and resources via the 'TMPDIR_CONTEXT_PROPERTY'.""" 442 443 raise NotImplementedError
444

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result_stream.ResultStream-class.html0000664000076400007640000006407211122067150030705 0ustar stefanstefan qm.test.result_stream.ResultStream
Package qm :: Package test :: Module result_stream :: Class ResultStream
[hide private]
[frames] | no frames]

Class ResultStream

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     ResultStream
Known Subclasses:

A 'ResultStream' displays test results.

A 'ResultStream' is responsible for displaying test results for the user as they arrive. It may also display summary information when the results are complete. The 'ResultStream' may also choose to write the results to a file for permanent storage.

'ResultStream' is an abstract class.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code
 
WriteAnnotation(self, key, value)
Output an annotation for this run.
source code
 
WriteAllAnnotations(self, annotations)
Output all annotations in 'annotations' to this stream.
source code
 
WriteResult(self, result)
Output a test result.
source code
 
Summarize(self)
Output summary information about the results.
source code
 
_GetExpectedOutcome(self, test_id)
Return the outcome expected for 'test_id'.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  kind = 'result_stream'
A string giving kind of extension is implemented by the class.
  expected_outcomes = None
  _argument_dictionary = {'expected_outcomes': <<class 'qm.field...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.PythonField'> expected_ou...
A list of all the 'Field's in this class.

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

WriteAnnotation(self, key, value)

source code 

Output an annotation for this run.

Subclasses should override this if they want to store/display annotations; the default implementation simply discards them.

'key' -- the key value as a string.

'value' -- the value of this annotation as a string.

WriteAllAnnotations(self, annotations)

source code 

Output all annotations in 'annotations' to this stream.

Currently this is the same as making repeated calls to 'WriteAnnotation', but in the future, as special annotation types like timestamps are added, this will do the work of dispatching to functions like 'WriteTimestamp'.

Should not be overridden by subclasses.

WriteResult(self, result)

source code 

Output a test result.

Subclasses must override this method; the default implementation raises a 'NotImplementedError'.

'result' -- A 'Result'.

Summarize(self)

source code 

Output summary information about the results.

When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point.

Derived class methods may override this method. They should, however, invoke this version before returning.

_GetExpectedOutcome(self, test_id)

source code 

Return the outcome expected for 'test_id'.

returns -- The outcome (one of the elements of 'Result.outcomes') expected for 'test_id'. The expected outcome is taken from the 'expected_outcomes' provided when constructing this result stream, if available. If no expected outcome is available the default value ('Result.PASS') will be returned.


Class Variable Details [hide private]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'expected_outcomes': <<class 'qm.fields.PythonField'> expected_outcom\
es>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.PythonField'> expected_outcomes>]

qmtest-2.4.1/share/doc/qmtest/html/manual/random.Random-class.html0000664000076400007640000012635111122067151024470 0ustar stefanstefan random.Random
random :: Random :: Class Random
[hide private]
[frames] | no frames]

Class Random

source code

    object --+    
             |    
_random.Random --+
                 |
                Random
Known Subclasses:

Random number generator base class used by bound module functions.

Used to instantiate instances of Random to get generators that don't share state. Especially useful for multi-threaded programs, creating a different instance of Random for each thread, and using the jumpahead() method to ensure that the generated sequences seen by each thread don't overlap.

Class Random can also be subclassed if you want to use a different basic generator of your own devising: in that case, override the following methods: random(), seed(), getstate(), setstate() and jumpahead(). Optionally, implement a getrandombits() method so that randrange() can cover arbitrarily large ranges.

Instance Methods [hide private]
 
__getstate__(self) source code
 
__init__(self, x=None)
Initialize an instance.
source code
 
__reduce__(self)
helper for pickle
source code
 
__setstate__(self, state) source code
 
_randbelow(self, n, _log=<built-in function log>, int=<type 'int'>, _maxwidth=9007199254740992, _Method=<type 'instancemethod'>, _BuiltinMethod=<type 'builtin_function_or_method'>)
Return a random int in the range [0,n)
source code
 
betavariate(self, alpha, beta)
Beta distribution.
source code
 
choice(self, seq)
Choose a random element from a non-empty sequence.
source code
 
expovariate(self, lambd)
Exponential distribution.
source code
 
gammavariate(self, alpha, beta)
Gamma distribution.
source code
 
gauss(self, mu, sigma)
Gaussian distribution.
source code
tuple containing the current state.
getstate(self)
Return internal state; can be passed to setstate() later.
source code
 
lognormvariate(self, mu, sigma)
Log normal distribution.
source code
 
normalvariate(self, mu, sigma)
Normal distribution.
source code
 
paretovariate(self, alpha)
Pareto distribution.
source code
 
randint(self, a, b)
Return random integer in range [a, b], including both end points.
source code
 
randrange(self, start, stop=None, step=1, int=<type 'int'>, default=None, maxwidth=9007199254740992)
Choose a random item from range(start, stop[, step]).
source code
 
sample(self, population, k)
Chooses k unique random elements from a population sequence.
source code
None
seed(self, a=None)
Initialize internal state from hashable object.
source code
None
setstate(self, state)
Restore internal state from object returned by getstate().
source code
 
shuffle(self, x, random=None, int=<type 'int'>)
x, random=random.random -> shuffle list x in place; return None.
source code
 
uniform(self, a, b)
Get a random number in the range [a, b).
source code
 
vonmisesvariate(self, mu, kappa)
Circular data distribution.
source code
 
weibullvariate(self, alpha, beta)
Weibull distribution.
source code

Inherited from _random.Random: __getattribute__, __new__, getrandbits, jumpahead, random

Inherited from object: __delattr__, __hash__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  VERSION = 2
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, x=None)
(Constructor)

source code 

Initialize an instance.

Optional argument x controls seeding, as for Random.seed().

Overrides: object.__init__

__reduce__(self)

source code 

helper for pickle

Overrides: object.__reduce__
(inherited documentation)

_randbelow(self, n, _log=<built-in function log>, int=<type 'int'>, _maxwidth=9007199254740992, _Method=<type 'instancemethod'>, _BuiltinMethod=<type 'builtin_function_or_method'>)

source code 

Return a random int in the range [0,n)

Handles the case where n has more bits than returned by a single call to the underlying generator.

betavariate(self, alpha, beta)

source code 

Beta distribution.

Conditions on the parameters are alpha > 0 and beta > 0. Returned values range between 0 and 1.

expovariate(self, lambd)

source code 

Exponential distribution.

lambd is 1.0 divided by the desired mean. (The parameter would be called "lambda", but that is a reserved word in Python.) Returned values range from 0 to positive infinity.

gammavariate(self, alpha, beta)

source code 

Gamma distribution. Not the gamma function!

Conditions on the parameters are alpha > 0 and beta > 0.

gauss(self, mu, sigma)

source code 

Gaussian distribution.

mu is the mean, and sigma is the standard deviation. This is slightly faster than the normalvariate() function.

Not thread-safe without a lock around calls.

getstate(self)

source code 

Return internal state; can be passed to setstate() later.

Returns: tuple containing the current state.
Overrides: _random.Random.getstate

lognormvariate(self, mu, sigma)

source code 

Log normal distribution.

If you take the natural logarithm of this distribution, you'll get a normal distribution with mean mu and standard deviation sigma. mu can have any value, and sigma must be greater than zero.

normalvariate(self, mu, sigma)

source code 

Normal distribution.

mu is the mean, and sigma is the standard deviation.

paretovariate(self, alpha)

source code 

Pareto distribution. alpha is the shape parameter.

randrange(self, start, stop=None, step=1, int=<type 'int'>, default=None, maxwidth=9007199254740992)

source code 

Choose a random item from range(start, stop[, step]).

This fixes the problem with randint() which includes the endpoint; in Python this is usually not what you want. Do not supply the 'int', 'default', and 'maxwidth' arguments.

sample(self, population, k)

source code 

Chooses k unique random elements from a population sequence.

Returns a new list containing elements from the population while leaving the original population unchanged. The resulting list is in selection order so that all sub-slices will also be valid random samples. This allows raffle winners (the sample) to be partitioned into grand prize and second place winners (the subslices).

Members of the population need not be hashable or unique. If the population contains repeats, then each occurrence is a possible selection in the sample.

To choose a sample in a range of integers, use xrange as an argument. This is especially fast and space efficient for sampling from a large population: sample(xrange(10000000), 60)

seed(self, a=None)

source code 

Initialize internal state from hashable object.

None or no argument seeds from current time or from an operating system specific randomness source if available.

If a is not None or an int or long, hash(a) is used instead.

Returns: None
Overrides: _random.Random.seed

setstate(self, state)

source code 

Restore internal state from object returned by getstate().

Returns: None
Overrides: _random.Random.setstate

shuffle(self, x, random=None, int=<type 'int'>)

source code 

x, random=random.random -> shuffle list x in place; return None.

Optional arg random is a 0-argument function returning a random float in [0.0, 1.0); by default, the standard random.random.

vonmisesvariate(self, mu, kappa)

source code 

Circular data distribution.

mu is the mean angle, expressed in radians between 0 and 2*pi, and kappa is the concentration parameter, which must be greater than or equal to zero. If kappa is equal to zero, this distribution reduces to a uniform random angle over the range 0 to 2*pi.

weibullvariate(self, alpha, beta)

source code 

Weibull distribution.

alpha is the scale parameter and beta is the shape parameter.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.AuthenticationError-class.html0000664000076400007640000001502011122067151027341 0ustar stefanstefan qm.user.AuthenticationError
qm :: user :: AuthenticationError :: Class AuthenticationError
[hide private]
[frames] | no frames]

Class AuthenticationError

source code

              object --+        
                       |        
exceptions.BaseException --+    
                           |    
        exceptions.Exception --+
                               |
                              AuthenticationError
Known Subclasses:

Instance Methods [hide private]

Inherited from exceptions.Exception: __init__, __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.report-pysrc.html0000664000076400007640000037167311122067161024743 0ustar stefanstefan qm.test.report
Package qm :: Package test :: Module report
[hide private]
[frames] | no frames]

Source Code for Module qm.test.report

  1  ######################################################################## 
  2  # 
  3  # File:   report.py 
  4  # Author: Stefan Seefeld 
  5  # Date:   2005-02-13 
  6  # 
  7  # Contents: 
  8  #   QMTest ReportGenerator class. 
  9  # 
 10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  import qm.xmlutil 
 22  from qm.common import PythonException 
 23  from qm.test import base 
 24  from qm.test.result import Result 
 25  from qm.test.reader_test_run import ReaderTestRun 
 26  import xml.sax 
 27  import sys 
 28   
 29  ######################################################################## 
 30  # Classes 
 31  ######################################################################## 
 32   
33 -class ReportGenerator:
34 """A 'ReportGenerator' generates a test report from one or more 35 result files.""" 36
37 - def __init__(self, output, database=None):
38 39 if output and output != '-': 40 self.output = open(output, 'w+') 41 else: 42 self.output = sys.stdout 43 self.database = database 44 self.__document = qm.xmlutil.create_dom_document( 45 public_id="QMTest/Report", 46 document_element_tag="report")
47 48
49 - def GenerateReport(self, flat, arguments):
50 """Generates a report file with results collected from a set of 51 result files. 52 53 'flat' -- True to indicate a flat result listing, False if tests should be 54 reported according to the database directory structure. 55 56 'arguments' -- command arguments of the form [result [-e expectation]]+ 57 58 returns -- None.""" 59 60 # Construct a list of (result / expectation file) tuples. 61 # As the expectation file is optional, see whether there 62 # is an '-e' option, and then adjust the remainder accordingly. 63 input = [] 64 while arguments: 65 if len(arguments) >= 3 and arguments[1] == '-e': 66 input.append((arguments[0], arguments[2])) 67 arguments = arguments[3:] 68 else: 69 input.append((arguments[0],None)) 70 arguments = arguments[1:] 71 72 # Write out the prologue. 73 self.output.write("<?xml version='1.0' encoding='ISO-8859-1'?>\n") 74 self.output.write("<report>\n") 75 76 test_runs = self._LoadTestRuns(input) 77 78 self.output.write(" <runs>\n") 79 for test_run, expectations in test_runs: 80 self.output.write(" <run>\n") 81 82 annotations = test_run.GetAnnotations() 83 for key, value in annotations.iteritems(): 84 85 element = self.__document.createElement("annotation") 86 element.setAttribute("key", key) 87 text = self.__document.createTextNode(value) 88 element.appendChild(text) 89 element.writexml(self.output, addindent = " ", newl = "\n") 90 self.output.write(" </run>\n") 91 self.output.write(" </runs>\n") 92 93 if flat: 94 self._ReportFlat(test_runs) 95 else: 96 self._Report(test_runs) 97 98 self.output.write("</report>\n")
99 100
101 - def _LoadTestRuns(self, input):
102 """Load test runs from the provided input. 103 104 'input' -- A list of pairs of file names referring to result files / 105 expectation files. The expectation file member may be None. 106 107 returns -- A list of pairs of TestRun objects.""" 108 109 runs = [] 110 for result_file, exp_file in input: 111 results = None 112 expectations = None 113 114 try: 115 file = result_file 116 reader = base.load_results(file, self.database) 117 results = ReaderTestRun(reader) 118 if exp_file: 119 file = exp_file 120 reader = base.load_results(file, self.database) 121 expectations = ReaderTestRun(reader) 122 except IOError, e: 123 raise PythonException("Error reading '%s'"%file, IOError, e) 124 except xml.sax.SAXException, e: 125 raise PythonException("Error loading '%s'"%file, 126 xml.sax.SAXException, e) 127 runs.append((results, expectations)) 128 return runs
129 130
131 - def _GetIds(self, test_runs):
132 """Return a list of ids to report results from. 133 This list is obtained from the database if it is present, 134 or else by taking the union of all items reported in the 135 test runs. 136 137 'test_runs' -- A list of result / expectation table pairs. 138 139 returns -- The tuple of resource-setup-ids, test-ids, 140 and resource-cleanup-ids.""" 141 142 test_ids = [] 143 resource_setup_ids = [] 144 resource_cleanup_ids = [] 145 if self.database: 146 test_ids = self.database.GetTestIds() 147 resource_setup_ids = self.database.GetResourceIds() 148 resource_cleanup_ids = resource_setup_ids 149 else: 150 for results, e in test_runs: 151 for result in results.GetAllResults("", Result.TEST): 152 if not result.GetId() in test_ids: 153 test_ids.append(result.GetId()) 154 for result in results.GetAllResults("", Result.RESOURCE_SETUP): 155 if not result.GetId() in resource_setup_ids: 156 resource_setup_ids.append(result.GetId()) 157 for result in results.GetAllResults("", Result.RESOURCE_CLEANUP): 158 if not result.GetId() in resource_cleanup_ids: 159 resource_cleanup_ids.append(result.GetId()) 160 return test_ids, resource_setup_ids, resource_cleanup_ids
161 162
163 - def _ReportFlat(self, test_runs):
164 """Generate test report with the given set of test runs. 165 The report will contain a flat list of item ids. 166 167 'test_runs' -- List of pairs of TestRun objects.""" 168 169 ids = self._GetIds(test_runs) 170 kinds = [Result.TEST, Result.RESOURCE_SETUP, Result.RESOURCE_CLEANUP] 171 172 element = self.__document.createElement('results') 173 # Report all items, sorted by their kind. 174 for k in [0, 1, 2]: 175 for id in ids[k]: 176 self._ReportItem(kinds[k], id, id, test_runs, element) 177 178 element.writexml(self.output, indent = " ", addindent = " ", 179 newl = "\n")
180 181
182 - def _Report(self, test_runs):
183 """Generate test report with the given set of test runs. 184 The report will contain a tree structure with items appearing in their 185 respective subdirectory. 186 187 'test_runs' -- List of pairs of TestRun objects.""" 188 189 element = self.__document.createElement('results') 190 root = self._ReportSubdirectory('', test_runs, element) 191 root.writexml(self.output, indent=" ", addindent=" ", newl="\n")
192 193
194 - def _ReportSubdirectory(self, directory, test_runs, element=None):
195 """Generate a DOM node for the given directory containing its results. 196 197 'directory' -- The directory for which to generate the report node. 198 199 'test_runs' -- The List of TestRuns. 200 201 'element' -- DOM element to store results into. 202 If this is None, an element will be created. 203 204 returns -- DOM element node containing the xmlified results.""" 205 206 if not element: 207 element = self.__document.createElement('subdirectory') 208 element.setAttribute('name', directory) 209 210 # Start with the subdirectories. 211 for dir in self.database.GetSubdirectories(directory): 212 child = self._ReportSubdirectory(dir, test_runs) 213 element.appendChild(child) 214 215 # Report all items, sorted by kind. 216 for id in self.database.GetIds('test', directory, False): 217 self._ReportItem('test', id, self.database.SplitLabel(id)[1], 218 test_runs, element) 219 for id in self.database.GetIds('resource', directory, False): 220 self._ReportItem('resource_setup', id, self.database.SplitLabel(id)[1], 221 test_runs, element) 222 self._ReportItem('resource_cleanup', id, self.database.SplitLabel(id)[1], 223 test_runs, element) 224 return element
225 226
227 - def _ReportItem(self, kind, item_id, name, test_runs, parent):
228 """Report a single item. 229 230 'kind' -- The kind of item to report. 231 232 'item_id' -- The item id to report. 233 234 'name' -- The item's name (usually either the absolute or relative id). 235 236 'test_runs' -- The list of test runs. 237 238 'parent' -- An XML element to insert new nodes into.""" 239 240 # Create one item node per id... 241 item = self.__document.createElement('item') 242 item.setAttribute('id', name) 243 item.setAttribute('kind', kind) 244 parent.appendChild(item) 245 246 # ...and fill it with one result per test run. 247 for results, expectations in test_runs: 248 result = results.GetResult(item_id, kind) 249 if not result: 250 result = Result(kind, item_id, Result.UNTESTED) 251 # Inject two new annotations containing the expectation values. 252 if expectations: 253 exp = expectations.GetResult(item_id, kind) 254 if exp: 255 result['qmtest.expected_outcome'] = exp.GetOutcome() 256 cause = exp.get('qmtest.cause') 257 if cause: 258 result['qmtest.expected_cause'] = cause 259 260 child = result.MakeDomNode(self.__document) 261 # Remove redundant attributes 262 child.removeAttribute('id') 263 child.removeAttribute('kind') 264 item.appendChild(child)
265

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.compiler-module.html0000664000076400007640000000313411122067144027567 0ustar stefanstefan compiler

Module compiler


Classes

Compiler
CompilerExecutable
Diagnostic
EDG
GCC
SourcePosition

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_database.TestFileError-class.html0000664000076400007640000001557511122067150032177 0ustar stefanstefan qm.test.classes.xml_database.TestFileError
Package qm :: Package test :: Package classes :: Module xml_database :: Class TestFileError
[hide private]
[frames] | no frames]

Class TestFileError

source code

              object --+                
                       |                
exceptions.BaseException --+            
                           |            
        exceptions.Exception --+        
                               |        
        exceptions.StandardError --+    
                                   |    
             exceptions.RuntimeError --+
                                       |
                                      TestFileError

An error in the format or contents of an XML test file.

Instance Methods [hide private]

Inherited from exceptions.RuntimeError: __init__, __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.execution_thread-module.html0000664000076400007640000000215411122067144027654 0ustar stefanstefan execution_thread

Module execution_thread


Classes

ExecutionThread

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.parameter_database-module.html0000664000076400007640000000216611122067144030131 0ustar stefanstefan parameter_database

Module parameter_database


Classes

ParameterDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.VSEval-module.html0000664000076400007640000000373111122067144031600 0ustar stefanstefan VSEval

Module VSEval


Classes

Eval

Functions

careful_mul
default_slicer

Variables

__rcs_id__
compiled_getattr
default_globals
gparse
nltosp

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.file_label-pysrc.html0000664000076400007640000004472011122067156027134 0ustar stefanstefan qm.test.classes.file_label
Package qm :: Package test :: Package classes :: Module file_label
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.file_label

 1  ######################################################################## 
 2  # 
 3  # File:   file_label.py 
 4  # Author: Mark Mitchell 
 5  # Date:   06/11/2002 
 6  # 
 7  # Contents: 
 8  #   FileLabel 
 9  # 
10  # Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ######################################################################## 
17   
18  from   qm.label   import * 
19  import os 
20  import re 
21   
22  ######################################################################## 
23  # Classes 
24  ######################################################################## 
25   
26 -class FileLabel(Label):
27 """A 'FileLabel' is a 'Label' that uses the filesystem's naming scheme. 28 29 A 'FileLabel' is a 'Label' whose separator character is the 30 operating system's file system separator character (typically '/' or 31 '\\'). These labels are not system-independent; there is no 32 guarantee that 'FileLabel's will have the same meaning on different 33 operating systems.""" 34 35 _sep = os.sep 36
37 - def Join(self, *labels):
38 """Combine this label and the 'labels' into a single label. 39 40 'labels' -- A sequence of strings giving the components of the 41 new label. All but the last are taken as directory names; the 42 last is treated as a basename.""" 43 44 return self.__class__(apply(os.path.join, (self._label,) + labels))
45 46
47 - def Split(self):
48 """Split the label into a pair '(directory, basename)'. 49 50 returns -- A pair '(directory, basename)', each of which is 51 a label. 52 53 It is always true that 'directory.join(basename)' will return a 54 label equivalent to the original label.""" 55 56 return os.path.split(self._label)
57 58
59 - def Basename(self):
60 """Return the basename for the label. 61 62 returns -- A string giving the basename for the label. The 63 value returned for 'l.basename()' is always the same as 64 'l.split()[1]'.""" 65 66 return os.path.basename(self._label)
67 68
69 - def Dirname(self):
70 """Return the directory name for the 'label'. 71 72 returns -- A string giving the directory name for the 'label'. 73 The value returned for 'l.dirname()' is always the same as 74 'l.split()[0]'.""" 75 76 return os.path.dirname(self._label)
77

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_In.InFactory-class.html0000664000076400007640000001542511122067146032334 0ustar stefanstefan qm.external.DocumentTemplate.DT_In.InFactory
Package qm :: Package external :: Package DocumentTemplate :: Module DT_In :: Class InFactory
[hide private]
[frames] | no frames]

Class InFactory

source code

Instance Methods [hide private]
 
__call__(self, blocks) source code
Class Variables [hide private]
  blockContinuations = ('else')
  name = 'in'
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.command_thread.CommandThread-class.html0000664000076400007640000005102311122067150031025 0ustar stefanstefan qm.test.command_thread.CommandThread
Package qm :: Package test :: Module command_thread :: Class CommandThread
[hide private]
[frames] | no frames]

Class CommandThread

source code

        object --+        
                 |        
threading._Verbose --+    
                     |    
      threading.Thread --+
                         |
                        CommandThread

A 'CommandThread' is a thread that executes commands.

The commands are written to a 'Queue' by a controlling thread. The 'CommandThread' extracts the commands and dispatches them to derived class methods that process them. This class is used as a base class for thread classes used by some targets.

The commands are written to the 'Queue' as Python objects. The normal commands have the form '(method, descriptor, context)' where 'method' is a string. At present, the only value used for 'method' is '_RunTest'. In that case 'descriptor' is a test descriptor and 'context' is a 'Context'. The 'Stop' command is provided as a simple string, not a tuple.

Instance Methods [hide private]
 
__init__(self, target)
Construct a new 'CommandThread'.
source code
 
run(self)
Execute the thread.
source code
 
GetTarget(self)
Return the 'Target' associated with this thread.
source code
 
RunTest(self, descriptor, context)
Run the test given by 'descriptor'.
source code
 
Stop(self)
Stop the thread.
source code
 
_RunTest(self, descriptor, context)
Run the test given by 'descriptor'.
source code
 
_Stop(self)
Stop the thread.
source code
 
_Trace(self, message)
Write a trace 'message'.
source code

Inherited from threading.Thread: __repr__, getName, isAlive, isDaemon, join, setDaemon, setName, start

Inherited from threading.Thread (private): _set_daemon

Inherited from threading._Verbose (private): _note

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, target)
(Constructor)

source code 

Construct a new 'CommandThread'.

'target' -- The 'Target' that owns this thread.

Overrides: object.__init__

run(self)

source code 

Execute the thread.

Overrides: threading.Thread.run

GetTarget(self)

source code 

Return the 'Target' associated with this thread.

returns -- The 'Target' with which this thread is associated.

Derived classes must not override this method.

RunTest(self, descriptor, context)

source code 

Run the test given by 'descriptor'.

'descriptor' -- The 'TestDescriptor' for the test to be run.

'context' -- The 'Context' in which to run the test.

This method is called by the controlling thread.

Derived classes must not override this method.

Stop(self)

source code 

Stop the thread.

Derived classes must not override this method.

_RunTest(self, descriptor, context)

source code 

Run the test given by 'descriptor'.

'descriptor' -- The 'TestDescriptor' for the test to be run.

'context' -- The 'Context' in which to run the test.

Derived classes must override this method.

_Stop(self)

source code 

Stop the thread.

This method is called in the thread after 'Stop' is called from the controlling thread. Derived classes can use this method to release resources before the thread is destroyed.

Derived classes may override this method.

_Trace(self, message)

source code 

Write a trace 'message'.

'message' -- A string to be output as a trace message.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.diagnostic.DiagnosticSet-class.html0000664000076400007640000002641111122067145027267 0ustar stefanstefan qm.diagnostic.DiagnosticSet
Package qm :: Module diagnostic :: Class DiagnosticSet
[hide private]
[frames] | no frames]

Class DiagnosticSet

source code

Instance Methods [hide private]
 
__init__(self)
Initialize a new set of diagnostics.
source code
 
ReadFromFile(self, path)
Load diagnostics from a file.
source code
 
Generate(self, tag, severity='error', output=None, **substitutions)
Generate a diagnostic message.
source code
Class Variables [hide private]
  __comment_regex = re.compile(r'(?m)^[ \t]*#.*$')
  __separator_regex = re.compile(r'(?m)^@')
Method Details [hide private]

ReadFromFile(self, path)

source code 

Load diagnostics from a file.

'path' -- Path to the file containing diagnostics.

Generate(self, tag, severity='error', output=None, **substitutions)

source code 

Generate a diagnostic message.

'tag' -- The tag of the diagnostic to generate.

'severity' -- A string representing the severity of the diagnostic, for instance "warning" or "error".

'output' -- If not 'None', the a file object to which the a full diagnostic is written.

'substitutions' -- Named values for substitution into the diagnostic message.

returns -- The bare diagnostic message.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-string-module.html0000664000076400007640000001136211122067145024240 0ustar stefanstefan string

Module string


Classes

Template
_TemplateMetaclass
_multimap

Functions

atof
atoi
atol
capitalize
capwords
center
count
expandtabs
find
index
join
joinfields
ljust
lower
lstrip
replace
rfind
rindex
rjust
rsplit
rstrip
split
splitfields
strip
swapcase
translate
upper
zfill

Variables

_idmap
_idmapL
ascii_letters
ascii_lowercase
ascii_uppercase
digits
hexdigits
letters
lowercase
octdigits
printable
punctuation
uppercase
whitespace

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.cmdline.CommandParser-class.html0000664000076400007640000005055711122067145026561 0ustar stefanstefan qm.cmdline.CommandParser
Package qm :: Module cmdline :: Class CommandParser
[hide private]
[frames] | no frames]

Class CommandParser

source code

Class for the functionality that parses the command line.

The command parser is used to easily specify a list of command line options and commands to be parsed from an argument list.

Instance Methods [hide private]
 
__init__(self, name, options, commands, conflicting_options=())
Create a new command parser.
source code
 
CheckOptions(self, options)
Check that a list of options 4-tuples is correct.
source code
 
BuildGetoptList(self, options)
Build a getopt list for the long options.
source code
 
BuildGetoptString(self, options)
Build a getopt string for the options passed in.
source code
 
GetOptionsHelp(self, options)
Return a string that is the basic help for options.
source code
 
GetBasicHelp(self)
Return a string that is the basic help for the commands.
source code
 
GetCommandHelp(self, command)
Return a string that is the help for a specific command.
source code
 
ParseCommandLine(self, argv)
Parse a command line.
source code
Method Details [hide private]

__init__(self, name, options, commands, conflicting_options=())
(Constructor)

source code 
Create a new command parser.

'name' -- The name of the executable that we are currently
using.  This will normally be argv[0].

'options' -- A list of 4-tuples specifying options that you wish
this parser to accept.  The 4-tuple has the following form:
(short_form, long_form, options, description).  'short_form'
must be exactly one character.  'long_form' must be specified
for every option in the list.  'arg_name' is a string
representing the name of the argument that is passed to this
option.  If it is 'None,' then this option doesn't take an
argument.  'description' is a string describing the option.

'commands' -- A list of 5-tuples specifying commands to be
accepted after the command line options.  The 5-tuple has the
form '(name, short_description, args_string, long_description,
options)'.

  'name' -- The string for the command.

  'short_description' -- A short description of the command to
  be printed out in general help.

  'args_string' -- The string that will be printed after the
  command in the command specific help.

  'long_description' -- The long description to be printed out
  in the command specfic help.

  'options' -- A list of 4-tuples of the same form as the
  'options' described above.

'conflicting_options' -- A sequence of sets of conflicting
options.  Each element is a sequence of option specifiers in the
same form as 'options', above.

CheckOptions(self, options)

source code 

Check that a list of options 4-tuples is correct.

'options' -- A list of 4-tuples as described above.

returns -- 1 if the options are all valid, 0 otherwise.

BuildGetoptList(self, options)

source code 

Build a getopt list for the long options.

'options' -- A list of 4-tuples as described above.

returns -- A list to be passed to getopt to parse long options.

BuildGetoptString(self, options)

source code 

Build a getopt string for the options passed in.

'options' -- A list of 4-tuples as described above.

returns -- A string to be passed to getopt to parse the options.

GetOptionsHelp(self, options)

source code 

Return a string that is the basic help for options.

options -- A list of options to get the help string for.

returns -- A string to be printed for the options.

GetBasicHelp(self)

source code 

Return a string that is the basic help for the commands.

returns -- A string to be printed with basic functionality of arguments and commands.

GetCommandHelp(self, command)

source code 

Return a string that is the help for a specific command.

command -- A string of the command that you want help for.

returns -- A string of help for a given command.

ParseCommandLine(self, argv)

source code 

Parse a command line.

'argv' -- A string containing the command line starting with argv[1]. It should not contain the name of the executed program.

returns -- A 4-tuple of the options given, the command given, the command options, and the command arguments. Its form is this: (options, command, command_options, command_args). 'options' is a list of 2-tuples indicating each option specified and the argument given to that option (if applicable). 'command' is the command given. 'command_options' is a list of 2-tuples indicating each option given to the command and its possible argument. 'command_args' is a list of arguments as given to the command. If no command is given, then the function will return '' for the command, [] for the arguments, and [] for the command options.

raises -- 'CommandError' if the command is invalid.


qmtest-2.4.1/share/doc/qmtest/html/manual/api-objects.txt0000664000076400007640000173133611122067163022752 0ustar stefanstefanmath math-module.html math.pow math-module.html#pow math.cosh math-module.html#cosh math.ldexp math-module.html#ldexp math.hypot math-module.html#hypot math.tan math-module.html#tan math.asin math-module.html#asin math.log math-module.html#log math.fabs math-module.html#fabs math.floor math-module.html#floor math.sqrt math-module.html#sqrt math.frexp math-module.html#frexp math.degrees math-module.html#degrees math.pi math-module.html#pi math.log10 math-module.html#log10 math.sin math-module.html#sin math.modf math-module.html#modf math.atan math-module.html#atan math.ceil math-module.html#ceil math.sinh math-module.html#sinh math.cos math-module.html#cos math.e math-module.html#e math.tanh math-module.html#tanh math.radians math-module.html#radians math.atan2 math-module.html#atan2 math.fmod math-module.html#fmod math.exp math-module.html#exp math.acos math-module.html#acos qm qm-module.html qm.open_temporary_file_fd qm.common-module.html#open_temporary_file_fd qm.format_time qm.common-module.html#format_time qm.get_lib_directory qm.common-module.html#get_lib_directory qm.prefix qm-module.html#prefix qm.warning qm.diagnostic-module.html#warning qm.split_path_fully qm.common-module.html#split_path_fully qm.parse_time qm.common-module.html#parse_time qm.message qm.diagnostic-module.html#message qm.read_assignments qm.common-module.html#read_assignments qm.split_argument_list qm.common-module.html#split_argument_list qm.open_temporary_file qm.common-module.html#open_temporary_file qm.get_username qm.common-module.html#get_username qm.parse_assignment qm.common-module.html#parse_assignment qm.load_module qm.common-module.html#load_module qm.get_doc_directory qm.common-module.html#get_doc_directory qm.get_userid qm.common-module.html#get_userid qm.parse_boolean qm.common-module.html#parse_boolean qm.html_to_text qm.common-module.html#html_to_text qm.close_file_on_exec qm.common-module.html#close_file_on_exec qm.wrap_lines qm.common-module.html#wrap_lines qm.parse_string_list qm.common-module.html#parse_string_list qm.version_info qm-module.html#version_info qm.parse_time_iso qm.common-module.html#parse_time_iso qm.make_unique_tag qm.common-module.html#make_unique_tag qm.load_class qm.common-module.html#load_class qm.convert_from_dos_text qm.common-module.html#convert_from_dos_text qm.copy qm.common-module.html#copy qm.format_time_iso qm.common-module.html#format_time_iso qm.format_traceback qm.common-module.html#format_traceback qm.format_exception qm.common-module.html#format_exception qm.error qm.diagnostic-module.html#error qm.get_share_directory qm.common-module.html#get_share_directory qm.attachment qm.attachment-module.html qm.attachment.make_temporary_location qm.attachment-module.html#make_temporary_location qm.attachment.make_dom_node qm.attachment-module.html#make_dom_node qm.attachment._temporary_location_prefix qm.attachment-module.html#_temporary_location_prefix qm.attachment.from_dom_node qm.attachment-module.html#from_dom_node qm.cmdline qm.cmdline-module.html qm.common qm.common-module.html qm.common.open_temporary_file_fd qm.common-module.html#open_temporary_file_fd qm.common.format_time qm.common-module.html#format_time qm.common.get_lib_directory qm.common-module.html#get_lib_directory qm.common.split_path_fully qm.common-module.html#split_path_fully qm.common.parse_time qm.common-module.html#parse_time qm.common.split_argument_list qm.common-module.html#split_argument_list qm.common.read_assignments qm.common-module.html#read_assignments qm.common._unique_tag qm.common-module.html#_unique_tag qm.common.open_temporary_file qm.common-module.html#open_temporary_file qm.common.__load_module_lock qm.common-module.html#__load_module_lock qm.common.get_username qm.common-module.html#get_username qm.common.parse_assignment qm.common-module.html#parse_assignment qm.common.load_module qm.common-module.html#load_module qm.common.get_doc_directory qm.common-module.html#get_doc_directory qm.common.get_userid qm.common-module.html#get_userid qm.common.rc qm.common-module.html#rc qm.common.parse_boolean qm.common-module.html#parse_boolean qm.common.html_to_text qm.common-module.html#html_to_text qm.common.close_file_on_exec qm.common-module.html#close_file_on_exec qm.common.wrap_lines qm.common-module.html#wrap_lines qm.common.parse_string_list qm.common-module.html#parse_string_list qm.common.parse_time_iso qm.common-module.html#parse_time_iso qm.common.make_unique_tag qm.common-module.html#make_unique_tag qm.common.load_class qm.common-module.html#load_class qm.common.convert_from_dos_text qm.common-module.html#convert_from_dos_text qm.common.program_name qm.common-module.html#program_name qm.common.copy qm.common-module.html#copy qm.common.format_time_iso qm.common-module.html#format_time_iso qm.common.format_traceback qm.common-module.html#format_traceback qm.common.format_exception qm.common-module.html#format_exception qm.common.get_share_directory qm.common-module.html#get_share_directory qm.config qm.config-module.html qm.config.doc_dir qm.config-module.html#doc_dir qm.config.version qm.config-module.html#version qm.config.data_dir qm.config-module.html#data_dir qm.config.extension_path qm.config-module.html#extension_path qm.db qm.db-module.html qm.db.quote_string qm.db-module.html#quote_string qm.diagnostic qm.diagnostic-module.html qm.diagnostic.get_diagnostic_set qm.diagnostic-module.html#get_diagnostic_set qm.diagnostic.__diagnostic_set qm.diagnostic-module.html#__diagnostic_set qm.diagnostic.get_help_set qm.diagnostic-module.html#get_help_set qm.diagnostic.__help_set qm.diagnostic-module.html#__help_set qm.diagnostic.warning qm.diagnostic-module.html#warning qm.diagnostic.error qm.diagnostic-module.html#error qm.diagnostic.message qm.diagnostic-module.html#message qm.diagnostic.load_messages qm.diagnostic-module.html#load_messages qm.dist qm.dist-module.html qm.dist.command qm.dist.command-module.html qm.dist.command.build_extensions qm.dist.command.build_extensions-module.html qm.dist.command.install_extensions qm.dist.command.install_extensions-module.html qm.dist.command.install_extensions._compare_files qm.dist.command.install_extensions-module.html#_compare_files qm.dist.distribution qm.dist.distribution-module.html qm.executable qm.executable-module.html qm.extension qm.extension-module.html qm.extension.make_dom_element qm.extension-module.html#make_dom_element qm.extension.parse_descriptor qm.extension-module.html#parse_descriptor qm.extension.write_extension_file qm.extension-module.html#write_extension_file qm.extension.get_class_arguments_as_dictionary qm.extension-module.html#get_class_arguments_as_dictionary qm.extension.read_extension_file qm.extension-module.html#read_extension_file qm.extension.make_dom_document qm.extension-module.html#make_dom_document qm.extension.get_class_arguments qm.extension-module.html#get_class_arguments qm.extension.parse_dom_element qm.extension-module.html#parse_dom_element qm.extension.validate_arguments qm.extension-module.html#validate_arguments qm.extension.get_extension_class_name qm.extension-module.html#get_extension_class_name qm.extension.get_class_description qm.extension-module.html#get_class_description qm.external qm.external-module.html qm.external.DocumentTemplate qm.external.DocumentTemplate-module.html qm.external.DocumentTemplate.__doc__ qm.external.DocumentTemplate-module.html#__doc__ qm.external.DocumentTemplate.DT_HTML qm.external.DocumentTemplate.DT_HTML-module.html qm.external.DocumentTemplate.DT_If qm.external.DocumentTemplate.DT_If-module.html qm.external.DocumentTemplate.DT_If.__rcs_id__ qm.external.DocumentTemplate.DT_If-module.html#__rcs_id__ qm.external.DocumentTemplate.DT_If.__doc__ qm.external.DocumentTemplate.DT_If-module.html#__doc__ qm.external.DocumentTemplate.DT_If.name_param qm.external.DocumentTemplate.DT_Util-module.html#name_param qm.external.DocumentTemplate.DT_If.parse_params qm.external.DocumentTemplate.DT_Util-module.html#parse_params qm.external.DocumentTemplate.DT_In qm.external.DocumentTemplate.DT_In-module.html qm.external.DocumentTemplate.DT_In.int_param qm.external.DocumentTemplate.DT_In-module.html#int_param qm.external.DocumentTemplate.DT_In.name_param qm.external.DocumentTemplate.DT_Util-module.html#name_param qm.external.DocumentTemplate.DT_In.basic_type qm.external.DocumentTemplate.DT_In-module.html#basic_type qm.external.DocumentTemplate.DT_In.__rcs_id__ qm.external.DocumentTemplate.DT_In-module.html#__rcs_id__ qm.external.DocumentTemplate.DT_In.render_blocks qm.external.DocumentTemplate.pDocumentTemplate-module.html#render_blocks qm.external.DocumentTemplate.DT_In.In qm.external.DocumentTemplate.DT_In-module.html#In qm.external.DocumentTemplate.DT_In.opt qm.external.DocumentTemplate.DT_InSV-module.html#opt qm.external.DocumentTemplate.DT_In.parse_params qm.external.DocumentTemplate.DT_Util-module.html#parse_params qm.external.DocumentTemplate.DT_InSV qm.external.DocumentTemplate.DT_InSV-module.html qm.external.DocumentTemplate.DT_InSV.opt qm.external.DocumentTemplate.DT_InSV-module.html#opt qm.external.DocumentTemplate.DT_InSV.sub qm.external.DocumentTemplate.DT_InSV-module.html#sub qm.external.DocumentTemplate.DT_InSV.mv qm.external.DocumentTemplate.DT_InSV-module.html#mv qm.external.DocumentTemplate.DT_InSV.__doc__ qm.external.DocumentTemplate.DT_InSV-module.html#__doc__ qm.external.DocumentTemplate.DT_Let qm.external.DocumentTemplate.DT_Let-module.html qm.external.DocumentTemplate.DT_Let.render_blocks qm.external.DocumentTemplate.pDocumentTemplate-module.html#render_blocks qm.external.DocumentTemplate.DT_Let.parse_let_params qm.external.DocumentTemplate.DT_Let-module.html#parse_let_params qm.external.DocumentTemplate.DT_Raise qm.external.DocumentTemplate.DT_Raise-module.html qm.external.DocumentTemplate.DT_Raise.__rcs_id__ qm.external.DocumentTemplate.DT_Raise-module.html#__rcs_id__ qm.external.DocumentTemplate.DT_Raise.render_blocks qm.external.DocumentTemplate.pDocumentTemplate-module.html#render_blocks qm.external.DocumentTemplate.DT_Raise.name_param qm.external.DocumentTemplate.DT_Util-module.html#name_param qm.external.DocumentTemplate.DT_Raise.parse_params qm.external.DocumentTemplate.DT_Util-module.html#parse_params qm.external.DocumentTemplate.DT_Return qm.external.DocumentTemplate.DT_Return-module.html qm.external.DocumentTemplate.DT_Return.name_param qm.external.DocumentTemplate.DT_Util-module.html#name_param qm.external.DocumentTemplate.DT_Return.html_quote qm.external.DocumentTemplate.DT_Util-module.html#html_quote qm.external.DocumentTemplate.DT_Return.parse_params qm.external.DocumentTemplate.DT_Util-module.html#parse_params qm.external.DocumentTemplate.DT_String qm.external.DocumentTemplate.DT_String-module.html qm.external.DocumentTemplate.DT_String._marker qm.external.DocumentTemplate.DT_String-module.html#_marker qm.external.DocumentTemplate.DT_String.render_blocks qm.external.DocumentTemplate.pDocumentTemplate-module.html#render_blocks qm.external.DocumentTemplate.DT_Try qm.external.DocumentTemplate.DT_Try-module.html qm.external.DocumentTemplate.DT_Try.namespace qm.external.DocumentTemplate.DT_Util-module.html#namespace qm.external.DocumentTemplate.DT_Try.render_blocks qm.external.DocumentTemplate.pDocumentTemplate-module.html#render_blocks qm.external.DocumentTemplate.DT_Try.parse_params qm.external.DocumentTemplate.DT_Util-module.html#parse_params qm.external.DocumentTemplate.DT_UI qm.external.DocumentTemplate.DT_UI-module.html qm.external.DocumentTemplate.DT_UI.FactoryDefaultString qm.external.DocumentTemplate.DT_UI-module.html#FactoryDefaultString qm.external.DocumentTemplate.DT_UI.__doc__ qm.external.DocumentTemplate.DT_UI-module.html#__doc__ qm.external.DocumentTemplate.DT_Util qm.external.DocumentTemplate.DT_Util-module.html qm.external.DocumentTemplate.DT_Util.render qm.external.DocumentTemplate.DT_Util-module.html#render qm.external.DocumentTemplate.DT_Util.careful_getslice qm.external.DocumentTemplate.DT_Util-module.html#careful_getslice qm.external.DocumentTemplate.DT_Util.obsolete_attr qm.external.DocumentTemplate.DT_Util-module.html#obsolete_attr qm.external.DocumentTemplate.DT_Util.expr_globals qm.external.DocumentTemplate.DT_Util-module.html#expr_globals qm.external.DocumentTemplate.DT_Util.namespace qm.external.DocumentTemplate.DT_Util-module.html#namespace qm.external.DocumentTemplate.DT_Util.test qm.external.DocumentTemplate.DT_Util-module.html#test qm.external.DocumentTemplate.DT_Util.careful_hasattr qm.external.DocumentTemplate.DT_Util-module.html#careful_hasattr qm.external.DocumentTemplate.DT_Util.int_param qm.external.DocumentTemplate.DT_Util-module.html#int_param qm.external.DocumentTemplate.DT_Util._marker qm.external.DocumentTemplate.DT_Util-module.html#_marker qm.external.DocumentTemplate.DT_Util.careful_getitem qm.external.DocumentTemplate.DT_Util-module.html#careful_getitem qm.external.DocumentTemplate.DT_Util.ValidationError qm.external.DocumentTemplate.DT_Util-module.html#ValidationError qm.external.DocumentTemplate.DT_Util.Expr_doc qm.external.DocumentTemplate.DT_Util-module.html#Expr_doc qm.external.DocumentTemplate.DT_Util.ParseError qm.external.DocumentTemplate.DT_Util-module.html#ParseError qm.external.DocumentTemplate.DT_Util.careful_range qm.external.DocumentTemplate.DT_Util-module.html#careful_range qm.external.DocumentTemplate.DT_Util.name_param qm.external.DocumentTemplate.DT_Util-module.html#name_param qm.external.DocumentTemplate.DT_Util.parse_params qm.external.DocumentTemplate.DT_Util-module.html#parse_params qm.external.DocumentTemplate.DT_Util.d qm.external.DocumentTemplate.DT_Util-module.html#d qm.external.DocumentTemplate.DT_Util.name qm.external.DocumentTemplate.DT_Util-module.html#name qm.external.DocumentTemplate.DT_Util.careful_pow qm.external.DocumentTemplate.DT_Util-module.html#careful_pow qm.external.DocumentTemplate.DT_Util.careful_getattr qm.external.DocumentTemplate.DT_Util-module.html#careful_getattr qm.external.DocumentTemplate.DT_Util.html_quote qm.external.DocumentTemplate.DT_Util-module.html#html_quote qm.external.DocumentTemplate.DT_Var qm.external.DocumentTemplate.DT_Var-module.html qm.external.DocumentTemplate.DT_Var.len_comma qm.external.DocumentTemplate.DT_Var-module.html#len_comma qm.external.DocumentTemplate.DT_Var.dollars_and_cents_with_commas qm.external.DocumentTemplate.DT_Var-module.html#dollars_and_cents_with_commas qm.external.DocumentTemplate.DT_Var.thousands_commas qm.external.DocumentTemplate.DT_Var-module.html#thousands_commas qm.external.DocumentTemplate.DT_Var.sql_quote qm.external.DocumentTemplate.DT_Var-module.html#sql_quote qm.external.DocumentTemplate.DT_Var.whole_dollars_with_commas qm.external.DocumentTemplate.DT_Var-module.html#whole_dollars_with_commas qm.external.DocumentTemplate.DT_Var.url_quote qm.external.DocumentTemplate.DT_Var-module.html#url_quote qm.external.DocumentTemplate.DT_Var.StructuredText qm.external.DocumentTemplate.DT_Var-module.html#StructuredText qm.external.DocumentTemplate.DT_Var.len_format qm.external.DocumentTemplate.DT_Var-module.html#len_format qm.external.DocumentTemplate.DT_Var.url_quote_plus qm.external.DocumentTemplate.DT_Var-module.html#url_quote_plus qm.external.DocumentTemplate.DT_Var.spacify qm.external.DocumentTemplate.DT_Var-module.html#spacify qm.external.DocumentTemplate.DT_Var.__doc__ qm.external.DocumentTemplate.DT_Var-module.html#__doc__ qm.external.DocumentTemplate.DT_Var.url_unquote_plus qm.external.DocumentTemplate.DT_Var-module.html#url_unquote_plus qm.external.DocumentTemplate.DT_Var.url_unquote qm.external.DocumentTemplate.DT_Var-module.html#url_unquote qm.external.DocumentTemplate.DT_Var.name_param qm.external.DocumentTemplate.DT_Util-module.html#name_param qm.external.DocumentTemplate.DT_Var.parse_params qm.external.DocumentTemplate.DT_Util-module.html#parse_params qm.external.DocumentTemplate.DT_Var.newline_to_br qm.external.DocumentTemplate.DT_Var-module.html#newline_to_br qm.external.DocumentTemplate.DT_Var.modifiers qm.external.DocumentTemplate.DT_Var-module.html#modifiers qm.external.DocumentTemplate.DT_Var.__rcs_id__ qm.external.DocumentTemplate.DT_Var-module.html#__rcs_id__ qm.external.DocumentTemplate.DT_Var.special_formats qm.external.DocumentTemplate.DT_Var-module.html#special_formats qm.external.DocumentTemplate.DT_Var.whole_dollars qm.external.DocumentTemplate.DT_Var-module.html#whole_dollars qm.external.DocumentTemplate.DT_Var.dollars_and_cents qm.external.DocumentTemplate.DT_Var-module.html#dollars_and_cents qm.external.DocumentTemplate.DT_Var.html_quote qm.external.DocumentTemplate.DT_Util-module.html#html_quote qm.external.DocumentTemplate.DT_Var.structured_text qm.external.DocumentTemplate.DT_Var-module.html#structured_text qm.external.DocumentTemplate.DT_With qm.external.DocumentTemplate.DT_With-module.html qm.external.DocumentTemplate.DT_With.__rcs_id__ qm.external.DocumentTemplate.DT_With-module.html#__rcs_id__ qm.external.DocumentTemplate.DT_With.render_blocks qm.external.DocumentTemplate.pDocumentTemplate-module.html#render_blocks qm.external.DocumentTemplate.DT_With.name_param qm.external.DocumentTemplate.DT_Util-module.html#name_param qm.external.DocumentTemplate.DT_With.parse_params qm.external.DocumentTemplate.DT_Util-module.html#parse_params qm.external.DocumentTemplate.DTtestExpr qm.external.DocumentTemplate.DTtestExpr-module.html qm.external.DocumentTemplate.DTtestExpr.test1 qm.external.DocumentTemplate.DTtestExpr-module.html#test1 qm.external.DocumentTemplate.DTtestExpr.test3 qm.external.DocumentTemplate.DTtestExpr-module.html#test3 qm.external.DocumentTemplate.DTtestExpr.test2 qm.external.DocumentTemplate.DTtestExpr-module.html#test2 qm.external.DocumentTemplate.DTtestExpr.html_quote qm.external.DocumentTemplate.DT_Util-module.html#html_quote qm.external.DocumentTemplate.DTtestExpr.__doc__ qm.external.DocumentTemplate.DTtestExpr-module.html#__doc__ qm.external.DocumentTemplate.DTtestExpr.test4 qm.external.DocumentTemplate.DTtestExpr-module.html#test4 qm.external.DocumentTemplate.DocumentTemplate qm.external.DocumentTemplate.DocumentTemplate-module.html qm.external.DocumentTemplate.DocumentTemplate.ParseError qm.external.DocumentTemplate.DocumentTemplate-module.html#ParseError qm.external.DocumentTemplate.DocumentTemplate.html_quote qm.external.DocumentTemplate.DT_Util-module.html#html_quote qm.external.DocumentTemplate.VSEval qm.external.DocumentTemplate.VSEval-module.html qm.external.DocumentTemplate.VSEval.default_globals qm.external.DocumentTemplate.VSEval-module.html#default_globals qm.external.DocumentTemplate.VSEval.compiled_getattr qm.external.DocumentTemplate.VSEval-module.html#compiled_getattr qm.external.DocumentTemplate.VSEval.__rcs_id__ qm.external.DocumentTemplate.VSEval-module.html#__rcs_id__ qm.external.DocumentTemplate.VSEval.careful_mul qm.external.DocumentTemplate.VSEval-module.html#careful_mul qm.external.DocumentTemplate.VSEval.default_slicer qm.external.DocumentTemplate.VSEval-module.html#default_slicer qm.external.DocumentTemplate.VSEval.nltosp qm.external.DocumentTemplate.VSEval-module.html#nltosp qm.external.DocumentTemplate.VSEval.gparse qm.external.DocumentTemplate.VSEval-module.html#gparse qm.external.DocumentTemplate.gparse qm.external.DocumentTemplate.gparse-module.html qm.external.DocumentTemplate.gparse.item_munge qm.external.DocumentTemplate.gparse-module.html#item_munge qm.external.DocumentTemplate.gparse.multi_munge qm.external.DocumentTemplate.gparse-module.html#multi_munge qm.external.DocumentTemplate.gparse.slice_munge qm.external.DocumentTemplate.gparse-module.html#slice_munge qm.external.DocumentTemplate.gparse.dot_munge qm.external.DocumentTemplate.gparse-module.html#dot_munge qm.external.DocumentTemplate.gparse.munge qm.external.DocumentTemplate.gparse-module.html#munge qm.external.DocumentTemplate.gparse.ParseError qm.external.DocumentTemplate.gparse-module.html#ParseError qm.external.DocumentTemplate.gparse.compile qm.external.DocumentTemplate.gparse-module.html#compile qm.external.DocumentTemplate.pDocumentTemplate qm.external.DocumentTemplate.pDocumentTemplate-module.html qm.external.DocumentTemplate.pDocumentTemplate.isFunctionType qm.external.DocumentTemplate.pDocumentTemplate-module.html#isFunctionType qm.external.DocumentTemplate.pDocumentTemplate.n qm.external.DocumentTemplate.pDocumentTemplate-module.html#n qm.external.DocumentTemplate.pDocumentTemplate.render_blocks qm.external.DocumentTemplate.pDocumentTemplate-module.html#render_blocks qm.external.DocumentTemplate.pDocumentTemplate.isSimpleType qm.external.DocumentTemplate.pDocumentTemplate-module.html#isSimpleType qm.external.DocumentTemplate.pDocumentTemplate.name qm.external.DocumentTemplate.pDocumentTemplate-module.html#name qm.external.DocumentTemplate.setup qm.external.DocumentTemplate.setup-module.html qm.fields qm.fields-module.html qm.host qm.host-module.html qm.label qm.label-module.html qm.label.thunk qm.label-module.html#thunk qm.label.__thunk_regex qm.label-module.html#__thunk_regex qm.lock qm.lock-module.html qm.platform qm.platform-module.html qm.platform.install_signal_handler qm.platform_unix-module.html#install_signal_handler qm.platform.get_shell_for_command qm.platform-module.html#get_shell_for_command qm.platform.open_in_browser qm.platform_unix-module.html#open_in_browser qm.platform.get_host_name qm.platform_unix-module.html#get_host_name qm.platform.get_signal_name qm.platform_unix-module.html#get_signal_name qm.platform.get_shell_for_script qm.platform-module.html#get_shell_for_script qm.platform_unix qm.platform_unix-module.html qm.platform_unix._initialize qm.platform_unix-module.html#_initialize qm.platform_unix.install_signal_handler qm.platform_unix-module.html#install_signal_handler qm.platform_unix.get_signal_name qm.platform_unix-module.html#get_signal_name qm.platform_unix.get_host_name qm.platform_unix-module.html#get_host_name qm.platform_unix._signal_handler qm.platform_unix-module.html#_signal_handler qm.platform_unix.open_in_browser qm.platform_unix-module.html#open_in_browser qm.platform_unix.default_shell qm.platform_unix-module.html#default_shell qm.platform_win32 qm.platform_win32-module.html qm.platform_win32.get_host_name qm.platform_win32-module.html#get_host_name qm.platform_win32._get_host_name qm.platform_win32-module.html#_get_host_name qm.platform_win32.open_in_browser qm.platform_win32-module.html#open_in_browser qm.platform_win32.default_shell qm.platform_win32-module.html#default_shell qm.queue qm.queue-module.html qm.setup qm.setup-module.html qm.setup.find_packages_r qm.setup-module.html#find_packages_r qm.setup.packages qm.setup-module.html#packages qm.structured_text qm.structured_text-module.html qm.structured_text.escape_html_entities qm.structured_text-module.html#escape_html_entities qm.structured_text.to_text qm.structured_text-module.html#to_text qm.structured_text.__paragraph_regexp qm.structured_text-module.html#__paragraph_regexp qm.structured_text.get_first_paragraph qm.structured_text-module.html#get_first_paragraph qm.structured_text.character qm.structured_text-module.html#character qm.structured_text._verbatim_regexp qm.structured_text-module.html#_verbatim_regexp qm.structured_text.get_rest qm.structured_text-module.html#get_rest qm.structured_text.to_html qm.structured_text-module.html#to_html qm.structured_text.get_first qm.structured_text-module.html#get_first qm.structured_text.__entity_char_replacement qm.structured_text-module.html#__entity_char_replacement qm.structured_text.entity qm.structured_text-module.html#entity qm.structured_text.get_paragraphs qm.structured_text-module.html#get_paragraphs qm.structured_text.html_help_text qm.structured_text-module.html#html_help_text qm.structured_text.__format qm.structured_text-module.html#__format qm.structured_text.__entity_char_regex qm.structured_text-module.html#__entity_char_regex qm.temporary_directory qm.temporary_directory-module.html qm.test qm.test-module.html qm.test.base qm.test.base-module.html qm.test.base.get_extension_class_names qm.test.base-module.html#get_extension_class_names qm.test.base.load_results qm.test.base-module.html#load_results qm.test.base.load_expectations qm.test.base-module.html#load_expectations qm.test.base.get_extension_class_names_in_directory qm.test.base-module.html#get_extension_class_names_in_directory qm.test.base.get_test_class qm.test.base-module.html#get_test_class qm.test.base.get_extension_class qm.test.base-module.html#get_extension_class qm.test.base.get_extension_classes qm.test.base-module.html#get_extension_classes qm.test.base.get_extension_directories qm.test.base-module.html#get_extension_directories qm.test.base._result_from_dom qm.test.base-module.html#_result_from_dom qm.test.base.__extension_bases qm.test.base-module.html#__extension_bases qm.test.base.load_outcomes qm.test.base-module.html#load_outcomes qm.test.base.__class_caches qm.test.base-module.html#__class_caches qm.test.base.get_resource_class qm.test.base-module.html#get_resource_class qm.test.base.get_extension_class_from_directory qm.test.base-module.html#get_extension_class_from_directory qm.test.base.extension_kinds qm.test.base-module.html#extension_kinds qm.test.classes qm.test.classes-module.html qm.test.classes.command qm.test.classes.command-module.html qm.test.classes.command_host qm.test.classes.command_host-module.html qm.test.classes.compilation_test qm.test.classes.compilation_test-module.html qm.test.classes.compilation_test._get_host qm.test.classes.compilation_test-module.html#_get_host qm.test.classes.compilation_test_database qm.test.classes.compilation_test_database-module.html qm.test.classes.compiler qm.test.classes.compiler-module.html qm.test.classes.compiler_table qm.test.classes.compiler_table-module.html qm.test.classes.compiler_test qm.test.classes.compiler_test-module.html qm.test.classes.dejagnu_base qm.test.classes.dejagnu_base-module.html qm.test.classes.dejagnu_stream qm.test.classes.dejagnu_stream-module.html qm.test.classes.dejagnu_test qm.test.classes.dejagnu_test-module.html qm.test.classes.dg_test qm.test.classes.dg_test-module.html qm.test.classes.dir_run_database qm.test.classes.dir_run_database-module.html qm.test.classes.explicit_suite qm.test.classes.explicit_suite-module.html qm.test.classes.file qm.test.classes.file-module.html qm.test.classes.file_label qm.test.classes.file_label-module.html qm.test.classes.file_label.thunk qm.label-module.html#thunk qm.test.classes.local_host qm.test.classes.local_host-module.html qm.test.classes.mount_database qm.test.classes.mount_database-module.html qm.test.classes.mount_database.get_lib_directory qm.common-module.html#get_lib_directory qm.test.classes.mount_database.split_path_fully qm.common-module.html#split_path_fully qm.test.classes.mount_database.load_module qm.common-module.html#load_module qm.test.classes.mount_database.read_assignments qm.common-module.html#read_assignments qm.test.classes.mount_database.html_to_text qm.common-module.html#html_to_text qm.test.classes.mount_database.get_share_directory qm.common-module.html#get_share_directory qm.test.classes.mount_database.open_temporary_file_fd qm.common-module.html#open_temporary_file_fd qm.test.classes.mount_database.wrap_lines qm.common-module.html#wrap_lines qm.test.classes.mount_database.parse_string_list qm.common-module.html#parse_string_list qm.test.classes.mount_database.format_time_iso qm.common-module.html#format_time_iso qm.test.classes.mount_database.get_resource_class qm.test.parameter_database-module.html#get_resource_class qm.test.classes.mount_database.get_extension_directories qm.test.parameter_database-module.html#get_extension_directories qm.test.classes.mount_database.get_username qm.common-module.html#get_username qm.test.classes.mount_database.get_doc_directory qm.common-module.html#get_doc_directory qm.test.classes.mount_database.make_unique_tag qm.common-module.html#make_unique_tag qm.test.classes.mount_database.CouldNotLoadExtensionError qm.test.parameter_database-module.html#CouldNotLoadExtensionError qm.test.classes.mount_database.get_extension_classes qm.test.parameter_database-module.html#get_extension_classes qm.test.classes.mount_database.open_temporary_file qm.common-module.html#open_temporary_file qm.test.classes.mount_database.get_extension_class qm.test.parameter_database-module.html#get_extension_class qm.test.classes.mount_database.load_expectations qm.test.parameter_database-module.html#load_expectations qm.test.classes.mount_database.split_argument_list qm.common-module.html#split_argument_list qm.test.classes.mount_database.get_extension_class_names qm.test.parameter_database-module.html#get_extension_class_names qm.test.classes.mount_database.load_outcomes qm.test.parameter_database-module.html#load_outcomes qm.test.classes.mount_database.parse_boolean qm.common-module.html#parse_boolean qm.test.classes.mount_database.close_file_on_exec qm.common-module.html#close_file_on_exec qm.test.classes.mount_database.thunk qm.label-module.html#thunk qm.test.classes.mount_database.copy qm.common-module.html#copy qm.test.classes.mount_database.format_exception qm.common-module.html#format_exception qm.test.classes.mount_database.load_results qm.test.parameter_database-module.html#load_results qm.test.classes.mount_database.format_time qm.common-module.html#format_time qm.test.classes.mount_database.parse_time qm.common-module.html#parse_time qm.test.classes.mount_database.parse_time_iso qm.common-module.html#parse_time_iso qm.test.classes.mount_database.parse_assignment qm.common-module.html#parse_assignment qm.test.classes.mount_database.get_test_class qm.test.parameter_database-module.html#get_test_class qm.test.classes.mount_database.get_userid qm.common-module.html#get_userid qm.test.classes.mount_database.load_class qm.common-module.html#load_class qm.test.classes.mount_database.convert_from_dos_text qm.common-module.html#convert_from_dos_text qm.test.classes.mount_database.get_extension_class_names_in_directory qm.test.parameter_database-module.html#get_extension_class_names_in_directory qm.test.classes.mount_database.format_traceback qm.common-module.html#format_traceback qm.test.classes.mount_database.get_extension_class_from_directory qm.test.parameter_database-module.html#get_extension_class_from_directory qm.test.classes.pickle_result_stream qm.test.classes.pickle_result_stream-module.html qm.test.classes.pickle_result_stream._annotation_sentinel qm.test.classes.pickle_result_stream-module.html#_annotation_sentinel qm.test.classes.pickle_result_stream._int_size qm.test.classes.pickle_result_stream-module.html#_int_size qm.test.classes.pickle_result_stream._int_format qm.test.classes.pickle_result_stream-module.html#_int_format qm.test.classes.previous_testrun qm.test.classes.previous_testrun-module.html qm.test.classes.process_target qm.test.classes.process_target-module.html qm.test.classes.python qm.test.classes.python-module.html qm.test.classes.python.make_namespaces qm.test.classes.python-module.html#make_namespaces qm.test.classes.python_label qm.test.classes.python_label-module.html qm.test.classes.python_label.thunk qm.label-module.html#thunk qm.test.classes.rsh_target qm.test.classes.rsh_target-module.html qm.test.classes.serial_target qm.test.classes.serial_target-module.html qm.test.classes.simulator qm.test.classes.simulator-module.html qm.test.classes.sql_result_stream qm.test.classes.sql_result_stream-module.html qm.test.classes.sql_result_stream.quote_string qm.db-module.html#quote_string qm.test.classes.ssh_host qm.test.classes.ssh_host-module.html qm.test.classes.temporary qm.test.classes.temporary-module.html qm.test.classes.temporary.set_targets qm.test.test-module.html#set_targets qm.test.classes.temporary.get_targets qm.test.test-module.html#get_targets qm.test.classes.tet_stream qm.test.classes.tet_stream-module.html qm.test.classes.text_result_stream qm.test.classes.text_result_stream-module.html qm.test.classes.thread_target qm.test.classes.thread_target-module.html qm.test.classes.xml_database qm.test.classes.xml_database-module.html qm.test.classes.xml_expectation_database qm.test.classes.xml_expectation_database-module.html qm.test.classes.xml_result_stream qm.test.classes.xml_result_stream-module.html qm.test.cmdline qm.test.cmdline-module.html qm.test.cmdline._the_qmtest qm.test.cmdline-module.html#_the_qmtest qm.test.cmdline.get_qmtest qm.test.cmdline-module.html#get_qmtest qm.test.cmdline._make_comma_separated_string qm.test.cmdline-module.html#_make_comma_separated_string qm.test.command_thread qm.test.command_thread-module.html qm.test.context qm.test.context-module.html qm.test.database qm.test.database-module.html qm.test.database.load_database qm.test.database-module.html#load_database qm.test.database.get_resource_class qm.test.base-module.html#get_resource_class qm.test.database.__the_database qm.test.database-module.html#__the_database qm.test.database.get_configuration_file qm.test.database-module.html#get_configuration_file qm.test.database.get_extension_directories qm.test.base-module.html#get_extension_directories qm.test.database.get_database qm.test.database-module.html#get_database qm.test.database.CouldNotLoadExtensionError qm.test.base.CouldNotLoadExtensionError-class.html qm.test.database.get_extension_classes qm.test.base-module.html#get_extension_classes qm.test.database.set_path qm.test.database-module.html#set_path qm.test.database.get_configuration_directory qm.test.database-module.html#get_configuration_directory qm.test.database.load_expectations qm.test.base-module.html#load_expectations qm.test.database.get_extension_class_names qm.test.base-module.html#get_extension_class_names qm.test.database.load_outcomes qm.test.base-module.html#load_outcomes qm.test.database.is_database qm.test.database-module.html#is_database qm.test.database.__the_db_path qm.test.database-module.html#__the_db_path qm.test.database.load_results qm.test.base-module.html#load_results qm.test.database.thunk qm.label-module.html#thunk qm.test.database.get_test_class qm.test.base-module.html#get_test_class qm.test.database.get_extension_class_names_in_directory qm.test.base-module.html#get_extension_class_names_in_directory qm.test.database.get_extension_class qm.test.base-module.html#get_extension_class qm.test.database.get_extension_class_from_directory qm.test.base-module.html#get_extension_class_from_directory qm.test.directory_suite qm.test.directory_suite-module.html qm.test.execution_engine qm.test.execution_engine-module.html qm.test.execution_thread qm.test.execution_thread-module.html qm.test.expectation_database qm.test.expectation_database-module.html qm.test.file_database qm.test.file_database-module.html qm.test.file_database.get_lib_directory qm.common-module.html#get_lib_directory qm.test.file_database.split_path_fully qm.common-module.html#split_path_fully qm.test.file_database.load_module qm.common-module.html#load_module qm.test.file_database.read_assignments qm.common-module.html#read_assignments qm.test.file_database.html_to_text qm.common-module.html#html_to_text qm.test.file_database.get_share_directory qm.common-module.html#get_share_directory qm.test.file_database.open_temporary_file_fd qm.common-module.html#open_temporary_file_fd qm.test.file_database.wrap_lines qm.common-module.html#wrap_lines qm.test.file_database.parse_string_list qm.common-module.html#parse_string_list qm.test.file_database.format_time_iso qm.common-module.html#format_time_iso qm.test.file_database.get_resource_class qm.test.parameter_database-module.html#get_resource_class qm.test.file_database.get_username qm.common-module.html#get_username qm.test.file_database.get_doc_directory qm.common-module.html#get_doc_directory qm.test.file_database.make_unique_tag qm.common-module.html#make_unique_tag qm.test.file_database.CouldNotLoadExtensionError qm.test.parameter_database-module.html#CouldNotLoadExtensionError qm.test.file_database.get_extension_classes qm.test.parameter_database-module.html#get_extension_classes qm.test.file_database.open_temporary_file qm.common-module.html#open_temporary_file qm.test.file_database.load_expectations qm.test.parameter_database-module.html#load_expectations qm.test.file_database.split_argument_list qm.common-module.html#split_argument_list qm.test.file_database.get_extension_class_names qm.test.parameter_database-module.html#get_extension_class_names qm.test.file_database.load_outcomes qm.test.parameter_database-module.html#load_outcomes qm.test.file_database.parse_boolean qm.common-module.html#parse_boolean qm.test.file_database.close_file_on_exec qm.common-module.html#close_file_on_exec qm.test.file_database.parse_time_iso qm.common-module.html#parse_time_iso qm.test.file_database.copy qm.common-module.html#copy qm.test.file_database.format_exception qm.common-module.html#format_exception qm.test.file_database.load_results qm.test.parameter_database-module.html#load_results qm.test.file_database.format_time qm.common-module.html#format_time qm.test.file_database.thunk qm.label-module.html#thunk qm.test.file_database.parse_time qm.common-module.html#parse_time qm.test.file_database.get_test_class qm.test.parameter_database-module.html#get_test_class qm.test.file_database.get_userid qm.common-module.html#get_userid qm.test.file_database.load_class qm.common-module.html#load_class qm.test.file_database.convert_from_dos_text qm.common-module.html#convert_from_dos_text qm.test.file_database.get_extension_class_names_in_directory qm.test.parameter_database-module.html#get_extension_class_names_in_directory qm.test.file_database.format_traceback qm.common-module.html#format_traceback qm.test.file_database.get_extension_class qm.test.parameter_database-module.html#get_extension_class qm.test.file_database.get_extension_directories qm.test.parameter_database-module.html#get_extension_directories qm.test.file_database.parse_assignment qm.common-module.html#parse_assignment qm.test.file_database.get_extension_class_from_directory qm.test.parameter_database-module.html#get_extension_class_from_directory qm.test.file_result_reader qm.test.file_result_reader-module.html qm.test.file_result_stream qm.test.file_result_stream-module.html qm.test.parameter_database qm.test.parameter_database-module.html qm.test.parameter_database.get_lib_directory qm.common-module.html#get_lib_directory qm.test.parameter_database.split_path_fully qm.common-module.html#split_path_fully qm.test.parameter_database.load_module qm.common-module.html#load_module qm.test.parameter_database.read_assignments qm.common-module.html#read_assignments qm.test.parameter_database.html_to_text qm.common-module.html#html_to_text qm.test.parameter_database.get_share_directory qm.common-module.html#get_share_directory qm.test.parameter_database.open_temporary_file_fd qm.common-module.html#open_temporary_file_fd qm.test.parameter_database.wrap_lines qm.common-module.html#wrap_lines qm.test.parameter_database.parse_string_list qm.common-module.html#parse_string_list qm.test.parameter_database.format_time_iso qm.common-module.html#format_time_iso qm.test.parameter_database.get_resource_class qm.test.parameter_database-module.html#get_resource_class qm.test.parameter_database.get_extension_directories qm.test.parameter_database-module.html#get_extension_directories qm.test.parameter_database.get_username qm.common-module.html#get_username qm.test.parameter_database.get_doc_directory qm.common-module.html#get_doc_directory qm.test.parameter_database.make_unique_tag qm.common-module.html#make_unique_tag qm.test.parameter_database.CouldNotLoadExtensionError qm.test.parameter_database-module.html#CouldNotLoadExtensionError qm.test.parameter_database.get_extension_classes qm.test.parameter_database-module.html#get_extension_classes qm.test.parameter_database.open_temporary_file qm.common-module.html#open_temporary_file qm.test.parameter_database.load_expectations qm.test.parameter_database-module.html#load_expectations qm.test.parameter_database.split_argument_list qm.common-module.html#split_argument_list qm.test.parameter_database.get_extension_class_names qm.test.parameter_database-module.html#get_extension_class_names qm.test.parameter_database.load_outcomes qm.test.parameter_database-module.html#load_outcomes qm.test.parameter_database.parse_boolean qm.common-module.html#parse_boolean qm.test.parameter_database.close_file_on_exec qm.common-module.html#close_file_on_exec qm.test.parameter_database.parse_time_iso qm.common-module.html#parse_time_iso qm.test.parameter_database.copy qm.common-module.html#copy qm.test.parameter_database.format_exception qm.common-module.html#format_exception qm.test.parameter_database.load_results qm.test.parameter_database-module.html#load_results qm.test.parameter_database.format_time qm.common-module.html#format_time qm.test.parameter_database.thunk qm.label-module.html#thunk qm.test.parameter_database.parse_time qm.common-module.html#parse_time qm.test.parameter_database.get_test_class qm.test.parameter_database-module.html#get_test_class qm.test.parameter_database.get_userid qm.common-module.html#get_userid qm.test.parameter_database.load_class qm.common-module.html#load_class qm.test.parameter_database.convert_from_dos_text qm.common-module.html#convert_from_dos_text qm.test.parameter_database.get_extension_class_names_in_directory qm.test.parameter_database-module.html#get_extension_class_names_in_directory qm.test.parameter_database.format_traceback qm.common-module.html#format_traceback qm.test.parameter_database.get_extension_class qm.test.parameter_database-module.html#get_extension_class qm.test.parameter_database.parse_assignment qm.common-module.html#parse_assignment qm.test.parameter_database.get_extension_class_from_directory qm.test.parameter_database-module.html#get_extension_class_from_directory qm.test.reader_test_run qm.test.reader_test_run-module.html qm.test.report qm.test.report-module.html qm.test.resource qm.test.resource-module.html qm.test.resource_adapter qm.test.resource_adapter-module.html qm.test.result qm.test.result-module.html qm.test.result_reader qm.test.result_reader-module.html qm.test.result_stream qm.test.result_stream-module.html qm.test.run_database qm.test.run_database-module.html qm.test.run_database.parse_time_iso qm.common-module.html#parse_time_iso qm.test.runnable qm.test.runnable-module.html qm.test.suite qm.test.suite-module.html qm.test.target qm.test.target-module.html qm.test.test qm.test.test-module.html qm.test.test.__the_targets qm.test.test-module.html#__the_targets qm.test.test.set_targets qm.test.test-module.html#set_targets qm.test.test.get_targets qm.test.test-module.html#get_targets qm.test.test_run qm.test.test_run-module.html qm.test.web qm.test.web-module.html qm.test.web.web qm.test.web.web-module.html qm.trace qm.trace-module.html qm.user qm.user-module.html qm.user.load_xml_database qm.user-module.html#load_xml_database qm.user.create_dom_for_group qm.user-module.html#create_dom_for_group qm.user._get_dom_properties qm.user-module.html#_get_dom_properties qm.user.get_user_from_dom qm.user-module.html#get_user_from_dom qm.user.get_group_from_dom qm.user-module.html#get_group_from_dom qm.user.authenticator qm.user-module.html#authenticator qm.user.create_dom_for_user qm.user-module.html#create_dom_for_user qm.user.xml_user_database_dtd qm.user-module.html#xml_user_database_dtd qm.user._create_dom_properties qm.user-module.html#_create_dom_properties qm.user.database qm.user-module.html#database qm.web qm.web-module.html qm.web.make_set_control qm.web-module.html#make_set_control qm.web.make_submit_button qm.web-module.html#make_submit_button qm.web.__replacement_for_entity qm.web-module.html#__replacement_for_entity qm.web.make_button_for_request qm.web-module.html#make_button_for_request qm.web.decode_properties qm.web-module.html#decode_properties qm.web.make_javascript_string qm.web-module.html#make_javascript_string qm.web.handle_login qm.web-module.html#handle_login qm.web.unescape qm.web-module.html#unescape qm.web.escape qm.web-module.html#escape qm.web.make_help_link_html qm.web-module.html#make_help_link_html qm.web.javascript_unescape qm.web-module.html#javascript_unescape qm.web.handle_logout qm.web-module.html#handle_logout qm.web.http_return_exception qm.web-module.html#http_return_exception qm.web.make_choose_control qm.web-module.html#make_choose_control qm.web.sessions qm.web-module.html#sessions qm.web.javascript_escape qm.web-module.html#javascript_escape qm.web.session_id_field qm.web-module.html#session_id_field qm.web.encode_set_control_contents qm.web-module.html#encode_set_control_contents qm.web.make_help_link qm.web-module.html#make_help_link qm.web.get_session qm.web-module.html#get_session qm.web.decode_set_control_contents qm.web-module.html#decode_set_control_contents qm.web.make_button_for_url qm.web-module.html#make_button_for_url qm.web._page_cache_name qm.web-module.html#_page_cache_name qm.web.__entity_regex qm.web-module.html#__entity_regex qm.web.generate_login_form qm.web-module.html#generate_login_form qm.web.format_color qm.web-module.html#format_color qm.web.generate_error_page qm.web-module.html#generate_error_page qm.web.make_properties_control qm.web-module.html#make_properties_control qm.web.http_return_html qm.web-module.html#http_return_html qm.web.parse_url_query qm.web-module.html#parse_url_query qm.web.make_url qm.web-module.html#make_url qm.web._counter qm.web-module.html#_counter qm.web.make_button_for_popup qm.web-module.html#make_button_for_popup qm.web.format_exception qm.web-module.html#format_exception qm.web.__clean_up_expired_sessions qm.web-module.html#__clean_up_expired_sessions qm.web._create_session_id qm.web-module.html#_create_session_id qm.web.format_structured_text qm.web-module.html#format_structured_text qm.web.encode_properties qm.web-module.html#encode_properties qm.web.make_popup_page qm.web-module.html#make_popup_page qm.web._session_cache_name qm.web-module.html#_session_cache_name qm.xmlutil qm.xmlutil-module.html qm.xmlutil.sanitize_text_for_comment qm.xmlutil-module.html#sanitize_text_for_comment qm.xmlutil.__hyphen_replacement qm.xmlutil-module.html#__hyphen_replacement qm.xmlutil.get_dom_text qm.xmlutil-module.html#get_dom_text qm.xmlutil.make_public_id qm.xmlutil-module.html#make_public_id qm.xmlutil.get_child_text qm.xmlutil-module.html#get_child_text qm.xmlutil.load_xml qm.xmlutil-module.html#load_xml qm.xmlutil.create_dom_text_element qm.xmlutil-module.html#create_dom_text_element qm.xmlutil.create_dom_document qm.xmlutil-module.html#create_dom_document qm.xmlutil.__dom_implementation qm.xmlutil-module.html#__dom_implementation qm.xmlutil.make_system_id qm.xmlutil-module.html#make_system_id qm.xmlutil.get_child_texts qm.xmlutil-module.html#get_child_texts qm.xmlutil.child_tag_predicate qm.xmlutil-module.html#child_tag_predicate qm.xmlutil.__hyphen_regex qm.xmlutil-module.html#__hyphen_regex qm.xmlutil.get_child qm.xmlutil-module.html#get_child qm.xmlutil.load_xml_file qm.xmlutil-module.html#load_xml_file random random-module.html random.randrange random-module.html#randrange random.BPF random-module.html#BPF random._test random-module.html#_test random.random random-module.html#random random.paretovariate random-module.html#paretovariate random.normalvariate random-module.html#normalvariate random.gammavariate random-module.html#gammavariate random.sample random-module.html#sample random.weibullvariate random-module.html#weibullvariate random.shuffle random-module.html#shuffle random.LOG4 random-module.html#LOG4 random._test_generator random-module.html#_test_generator random.randint random-module.html#randint random.vonmisesvariate random-module.html#vonmisesvariate random._pi random-module.html#_pi random.uniform random-module.html#uniform random.expovariate random-module.html#expovariate random.betavariate random-module.html#betavariate random._e random-module.html#_e random.getrandbits random-module.html#getrandbits random.setstate random-module.html#setstate random.lognormvariate random-module.html#lognormvariate random.TWOPI random-module.html#TWOPI random.gauss random-module.html#gauss random.jumpahead random-module.html#jumpahead random.choice random-module.html#choice random.RECIP_BPF random-module.html#RECIP_BPF random._inst random-module.html#_inst random.getstate random-module.html#getstate random.SG_MAGICCONST random-module.html#SG_MAGICCONST random.seed random-module.html#seed random.NV_MAGICCONST random-module.html#NV_MAGICCONST string string-module.html string.ascii_lowercase string-module.html#ascii_lowercase string.upper string-module.html#upper string.letters string-module.html#letters string.lstrip string-module.html#lstrip string.capitalize string-module.html#capitalize string.ascii_letters string-module.html#ascii_letters string.replace string-module.html#replace string.capwords string-module.html#capwords string.rfind string-module.html#rfind string.strip string-module.html#strip string.ascii_uppercase string-module.html#ascii_uppercase string.find string-module.html#find string.index string-module.html#index string.ljust string-module.html#ljust string._idmapL string-module.html#_idmapL string.rindex string-module.html#rindex string.octdigits string-module.html#octdigits string.splitfields string-module.html#splitfields string.split string-module.html#split string.rstrip string-module.html#rstrip string.uppercase string-module.html#uppercase string.translate string-module.html#translate string.punctuation string-module.html#punctuation string.digits string-module.html#digits string.joinfields string-module.html#joinfields string.rjust string-module.html#rjust string.printable string-module.html#printable string.lowercase string-module.html#lowercase string.swapcase string-module.html#swapcase string.atoi string-module.html#atoi string.hexdigits string-module.html#hexdigits string.atol string-module.html#atol string.atof string-module.html#atof string.whitespace string-module.html#whitespace string.count string-module.html#count string.lower string-module.html#lower string.join string-module.html#join string.center string-module.html#center string.rsplit string-module.html#rsplit string.expandtabs string-module.html#expandtabs string.zfill string-module.html#zfill string._idmap string-module.html#_idmap float float-class.html float.__int__ float-class.html#__int__ float.__rtruediv__ float-class.html#__rtruediv__ float.__str__ float-class.html#__str__ float.__getattribute__ float-class.html#__getattribute__ float.__radd__ float-class.html#__radd__ float.__getformat__ float-class.html#__getformat__ float.__truediv__ float-class.html#__truediv__ float.__rsub__ float-class.html#__rsub__ float.__rdiv__ float-class.html#__rdiv__ float.__rmul__ float-class.html#__rmul__ float.__lt__ float-class.html#__lt__ float.__getnewargs__ float-class.html#__getnewargs__ float.__rmod__ float-class.html#__rmod__ float.__float__ float-class.html#__float__ float.__rpow__ float-class.html#__rpow__ float.__new__ float-class.html#__new__ float.__abs__ float-class.html#__abs__ float.__pos__ float-class.html#__pos__ float.__sub__ float-class.html#__sub__ float.__rfloordiv__ float-class.html#__rfloordiv__ float.__neg__ float-class.html#__neg__ float.__ne__ float-class.html#__ne__ float.__rdivmod__ float-class.html#__rdivmod__ float.__coerce__ float-class.html#__coerce__ float.__divmod__ float-class.html#__divmod__ float.__add__ float-class.html#__add__ float.__gt__ float-class.html#__gt__ float.__eq__ float-class.html#__eq__ float.__repr__ float-class.html#__repr__ float.__nonzero__ float-class.html#__nonzero__ float.__mod__ float-class.html#__mod__ float.__div__ float-class.html#__div__ float.__le__ float-class.html#__le__ float.__mul__ float-class.html#__mul__ float.__floordiv__ float-class.html#__floordiv__ float.__hash__ float-class.html#__hash__ float.__setformat__ float-class.html#__setformat__ float.__long__ float-class.html#__long__ float.__ge__ float-class.html#__ge__ float.__pow__ float-class.html#__pow__ int int-class.html int.__int__ int-class.html#__int__ int.__ror__ int-class.html#__ror__ int.__rtruediv__ int-class.html#__rtruediv__ int.__add__ int-class.html#__add__ int.__str__ int-class.html#__str__ int.__getattribute__ int-class.html#__getattribute__ int.__radd__ int-class.html#__radd__ int.__and__ int-class.html#__and__ int.__truediv__ int-class.html#__truediv__ int.__rrshift__ int-class.html#__rrshift__ int.__rsub__ int-class.html#__rsub__ int.__rdiv__ int-class.html#__rdiv__ int.__rmul__ int-class.html#__rmul__ int.__rmod__ int-class.html#__rmod__ int.__getnewargs__ int-class.html#__getnewargs__ int.__float__ int-class.html#__float__ int.__rpow__ int-class.html#__rpow__ int.__rand__ int-class.html#__rand__ int.__divmod__ int-class.html#__divmod__ int.__new__ int-class.html#__new__ int.__pos__ int-class.html#__pos__ int.__cmp__ int-class.html#__cmp__ int.__abs__ int-class.html#__abs__ int.__rfloordiv__ int-class.html#__rfloordiv__ int.__mul__ int-class.html#__mul__ int.__rshift__ int-class.html#__rshift__ int.__rdivmod__ int-class.html#__rdivmod__ int.__invert__ int-class.html#__invert__ int.__coerce__ int-class.html#__coerce__ int.__pow__ int-class.html#__pow__ int.__rlshift__ int-class.html#__rlshift__ int.__lshift__ int-class.html#__lshift__ int.__sub__ int-class.html#__sub__ int.__hex__ int-class.html#__hex__ int.__oct__ int-class.html#__oct__ int.__rxor__ int-class.html#__rxor__ int.__nonzero__ int-class.html#__nonzero__ int.__mod__ int-class.html#__mod__ int.__neg__ int-class.html#__neg__ int.__xor__ int-class.html#__xor__ int.__div__ int-class.html#__div__ int.__repr__ int-class.html#__repr__ int.__floordiv__ int-class.html#__floordiv__ int.__hash__ int-class.html#__hash__ int.__index__ int-class.html#__index__ int.__long__ int-class.html#__long__ int.__or__ int-class.html#__or__ mimetools.Message mimetools.Message-class.html mimetools.Message.getmaintype mimetools.Message-class.html#getmaintype mimetools.Message.getsubtype mimetools.Message-class.html#getsubtype mimetools.Message.parseplist mimetools.Message-class.html#parseplist mimetools.Message.__init__ mimetools.Message-class.html#__init__ mimetools.Message.getparamnames mimetools.Message-class.html#getparamnames mimetools.Message.getencoding mimetools.Message-class.html#getencoding mimetools.Message.getparam mimetools.Message-class.html#getparam mimetools.Message.parsetype mimetools.Message-class.html#parsetype mimetools.Message.getplist mimetools.Message-class.html#getplist mimetools.Message.gettype mimetools.Message-class.html#gettype qm.attachment.Attachment qm.attachment.Attachment-class.html qm.attachment.Attachment.GetFileName qm.attachment.Attachment-class.html#GetFileName qm.attachment.Attachment.GetLocation qm.attachment.Attachment-class.html#GetLocation qm.attachment.Attachment.GetStore qm.attachment.Attachment-class.html#GetStore qm.attachment.Attachment.__str__ qm.attachment.Attachment-class.html#__str__ qm.attachment.Attachment.Move qm.attachment.Attachment-class.html#Move qm.attachment.Attachment.GetDescription qm.attachment.Attachment-class.html#GetDescription qm.attachment.Attachment.__cmp__ qm.attachment.Attachment-class.html#__cmp__ qm.attachment.Attachment.GetData qm.attachment.Attachment-class.html#GetData qm.attachment.Attachment.GetDataFile qm.attachment.Attachment-class.html#GetDataFile qm.attachment.Attachment.__init__ qm.attachment.Attachment-class.html#__init__ qm.attachment.Attachment.GetMimeType qm.attachment.Attachment-class.html#GetMimeType qm.attachment.AttachmentStore qm.attachment.AttachmentStore-class.html qm.attachment.AttachmentStore.GetSize qm.attachment.AttachmentStore-class.html#GetSize qm.attachment.AttachmentStore.HandleDownloadRequest qm.attachment.AttachmentStore-class.html#HandleDownloadRequest qm.attachment.AttachmentStore.GetData qm.attachment.AttachmentStore-class.html#GetData qm.attachment.AttachmentStore.GetDataFile qm.attachment.AttachmentStore-class.html#GetDataFile qm.attachment.AttachmentStore.Store qm.attachment.AttachmentStore-class.html#Store qm.attachment.FileAttachmentStore qm.attachment.FileAttachmentStore-class.html qm.attachment.FileAttachmentStore.Remove qm.attachment.FileAttachmentStore-class.html#Remove qm.attachment.FileAttachmentStore.GetSize qm.attachment.FileAttachmentStore-class.html#GetSize qm.attachment.AttachmentStore.HandleDownloadRequest qm.attachment.AttachmentStore-class.html#HandleDownloadRequest qm.attachment.FileAttachmentStore.__init__ qm.attachment.FileAttachmentStore-class.html#__init__ qm.attachment.FileAttachmentStore.GetData qm.attachment.FileAttachmentStore-class.html#GetData qm.attachment.FileAttachmentStore.GetDataFile qm.attachment.FileAttachmentStore-class.html#GetDataFile qm.attachment.FileAttachmentStore.Store qm.attachment.FileAttachmentStore-class.html#Store qm.attachment.TemporaryAttachmentStore qm.attachment.TemporaryAttachmentStore-class.html qm.attachment.FileAttachmentStore.Remove qm.attachment.FileAttachmentStore-class.html#Remove qm.attachment.FileAttachmentStore.GetSize qm.attachment.FileAttachmentStore-class.html#GetSize qm.attachment.AttachmentStore.HandleDownloadRequest qm.attachment.AttachmentStore-class.html#HandleDownloadRequest qm.attachment.FileAttachmentStore.Store qm.attachment.FileAttachmentStore-class.html#Store qm.attachment.FileAttachmentStore.GetData qm.attachment.FileAttachmentStore-class.html#GetData qm.attachment.FileAttachmentStore.GetDataFile qm.attachment.FileAttachmentStore-class.html#GetDataFile qm.attachment.TemporaryAttachmentStore.__init__ qm.attachment.TemporaryAttachmentStore-class.html#__init__ qm.attachment.TemporaryAttachmentStore.HandleUploadRequest qm.attachment.TemporaryAttachmentStore-class.html#HandleUploadRequest qm.cmdline.CommandError qm.cmdline.CommandError-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.cmdline.CommandParser qm.cmdline.CommandParser-class.html qm.cmdline.CommandParser.GetBasicHelp qm.cmdline.CommandParser-class.html#GetBasicHelp qm.cmdline.CommandParser.GetOptionsHelp qm.cmdline.CommandParser-class.html#GetOptionsHelp qm.cmdline.CommandParser.CheckOptions qm.cmdline.CommandParser-class.html#CheckOptions qm.cmdline.CommandParser.GetCommandHelp qm.cmdline.CommandParser-class.html#GetCommandHelp qm.cmdline.CommandParser.BuildGetoptString qm.cmdline.CommandParser-class.html#BuildGetoptString qm.cmdline.CommandParser.ParseCommandLine qm.cmdline.CommandParser-class.html#ParseCommandLine qm.cmdline.CommandParser.BuildGetoptList qm.cmdline.CommandParser-class.html#BuildGetoptList qm.cmdline.CommandParser.__init__ qm.cmdline.CommandParser-class.html#__init__ qm.common.PythonException qm.common.PythonException-class.html qm.common.PythonException.__init__ qm.common.PythonException-class.html#__init__ qm.common.QMException qm.common.QMException-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.common.RcConfiguration qm.common.RcConfiguration-class.html qm.common.RcConfiguration.__init__ qm.common.RcConfiguration-class.html#__init__ qm.common.RcConfiguration.Get qm.common.RcConfiguration-class.html#Get qm.common.RcConfiguration.user_rc_file_name qm.common.RcConfiguration-class.html#user_rc_file_name qm.common.RcConfiguration.GetOptions qm.common.RcConfiguration-class.html#GetOptions qm.common.RcConfiguration.Load qm.common.RcConfiguration-class.html#Load qm.common.UserError qm.common.UserError-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.db.Connection qm.db.Connection-class.html qm.db.Connection.commit qm.db.Connection-class.html#commit qm.db.Connection.execute qm.db.Connection-class.html#execute qm.db.Connection.rollback qm.db.Connection-class.html#rollback qm.db.Connection.__init__ qm.db.Connection-class.html#__init__ qm.db.Connection.close qm.db.Connection-class.html#close qm.diagnostic.DiagnosticSet qm.diagnostic.DiagnosticSet-class.html qm.diagnostic.DiagnosticSet.__init__ qm.diagnostic.DiagnosticSet-class.html#__init__ qm.diagnostic.DiagnosticSet.ReadFromFile qm.diagnostic.DiagnosticSet-class.html#ReadFromFile qm.diagnostic.DiagnosticSet.__comment_regex qm.diagnostic.DiagnosticSet-class.html#__comment_regex qm.diagnostic.DiagnosticSet.__separator_regex qm.diagnostic.DiagnosticSet-class.html#__separator_regex qm.diagnostic.DiagnosticSet.Generate qm.diagnostic.DiagnosticSet-class.html#Generate qm.dist.command.build_extensions.build_extensions qm.dist.command.build_extensions.build_extensions-class.html qm.dist.command.build_extensions.build_extensions.run qm.dist.command.build_extensions.build_extensions-class.html#run qm.dist.command.build_extensions.build_extensions.description qm.dist.command.build_extensions.build_extensions-class.html#description qm.dist.command.build_extensions.build_extensions.finalize_options qm.dist.command.build_extensions.build_extensions-class.html#finalize_options qm.dist.command.build_extensions.build_extensions.get_input qm.dist.command.build_extensions.build_extensions-class.html#get_input qm.dist.command.install_extensions.install_extensions qm.dist.command.install_extensions.install_extensions-class.html qm.dist.command.install_extensions.install_extensions.run qm.dist.command.install_extensions.install_extensions-class.html#run qm.dist.command.install_extensions.install_extensions.description qm.dist.command.install_extensions.install_extensions-class.html#description qm.dist.command.install_extensions.install_extensions.finalize_options qm.dist.command.install_extensions.install_extensions-class.html#finalize_options qm.dist.distribution.Distribution qm.dist.distribution.Distribution-class.html qm.dist.distribution.Distribution.__init__ qm.dist.distribution.Distribution-class.html#__init__ qm.executable.Executable qm.executable.Executable-class.html qm.executable.Executable.Spawn qm.executable.Executable-class.html#Spawn qm.executable.Executable.__CreateCommandLine qm.executable.Executable-class.html#__CreateCommandLine qm.executable.Executable.Run qm.executable.Executable-class.html#Run qm.executable.Executable._DoParent qm.executable.Executable-class.html#_DoParent qm.executable.Executable._InitializeParent qm.executable.Executable-class.html#_InitializeParent qm.executable.Executable._InitializeChild qm.executable.Executable-class.html#_InitializeChild qm.executable.Executable._HandleChild qm.executable.Executable-class.html#_HandleChild qm.executable.Executable.Kill qm.executable.Executable-class.html#Kill qm.executable.Executable._GetChildPID qm.executable.Executable-class.html#_GetChildPID qm.executable.Filter qm.executable.Filter-class.html qm.executable.RedirectedExecutable._InitializeParent qm.executable.RedirectedExecutable-class.html#_InitializeParent qm.executable.RedirectedExecutable._ClosePipeEnd qm.executable.RedirectedExecutable-class.html#_ClosePipeEnd qm.executable.Filter.__init__ qm.executable.Filter-class.html#__init__ qm.executable.TimeoutExecutable.Run qm.executable.TimeoutExecutable-class.html#Run qm.executable.RedirectedExecutable._HandleChild qm.executable.RedirectedExecutable-class.html#_HandleChild qm.executable.RedirectedExecutable._StdinPipe qm.executable.RedirectedExecutable-class.html#_StdinPipe qm.executable.RedirectedExecutable._StderrPipe qm.executable.RedirectedExecutable-class.html#_StderrPipe qm.executable.Executable._GetChildPID qm.executable.Executable-class.html#_GetChildPID qm.executable.RedirectedExecutable._DoParent qm.executable.RedirectedExecutable-class.html#_DoParent qm.executable.RedirectedExecutable._CreatePipe qm.executable.RedirectedExecutable-class.html#_CreatePipe qm.executable.RedirectedExecutable._ReadStdout qm.executable.RedirectedExecutable-class.html#_ReadStdout qm.executable.RedirectedExecutable._StdoutPipe qm.executable.RedirectedExecutable-class.html#_StdoutPipe qm.executable.Executable.Spawn qm.executable.Executable-class.html#Spawn qm.executable.RedirectedExecutable._ReadStderr qm.executable.RedirectedExecutable-class.html#_ReadStderr qm.executable.RedirectedExecutable._InitializeChild qm.executable.RedirectedExecutable-class.html#_InitializeChild qm.executable.Filter._WriteStdin qm.executable.Filter-class.html#_WriteStdin qm.executable.Executable.Kill qm.executable.Executable-class.html#Kill qm.executable.RedirectedExecutable qm.executable.RedirectedExecutable-class.html qm.executable.RedirectedExecutable._InitializeParent qm.executable.RedirectedExecutable-class.html#_InitializeParent qm.executable.RedirectedExecutable.__UninheritableHandle qm.executable.RedirectedExecutable-class.html#__UninheritableHandle qm.executable.RedirectedExecutable._ClosePipeEnd qm.executable.RedirectedExecutable-class.html#_ClosePipeEnd qm.executable.TimeoutExecutable.__init__ qm.executable.TimeoutExecutable-class.html#__init__ qm.executable.TimeoutExecutable.Run qm.executable.TimeoutExecutable-class.html#Run qm.executable.RedirectedExecutable.__CallUntilNone qm.executable.RedirectedExecutable-class.html#__CallUntilNone qm.executable.RedirectedExecutable._HandleChild qm.executable.RedirectedExecutable-class.html#_HandleChild qm.executable.RedirectedExecutable._StdinPipe qm.executable.RedirectedExecutable-class.html#_StdinPipe qm.executable.RedirectedExecutable._StderrPipe qm.executable.RedirectedExecutable-class.html#_StderrPipe qm.executable.Executable._GetChildPID qm.executable.Executable-class.html#_GetChildPID qm.executable.RedirectedExecutable._DoParent qm.executable.RedirectedExecutable-class.html#_DoParent qm.executable.RedirectedExecutable._CreatePipe qm.executable.RedirectedExecutable-class.html#_CreatePipe qm.executable.RedirectedExecutable._ReadStdout qm.executable.RedirectedExecutable-class.html#_ReadStdout qm.executable.RedirectedExecutable._StdoutPipe qm.executable.RedirectedExecutable-class.html#_StdoutPipe qm.executable.Executable.Spawn qm.executable.Executable-class.html#Spawn qm.executable.RedirectedExecutable._ReadStderr qm.executable.RedirectedExecutable-class.html#_ReadStderr qm.executable.RedirectedExecutable._InitializeChild qm.executable.RedirectedExecutable-class.html#_InitializeChild qm.executable.RedirectedExecutable._WriteStdin qm.executable.RedirectedExecutable-class.html#_WriteStdin qm.executable.Executable.Kill qm.executable.Executable-class.html#Kill qm.executable.TimeoutExecutable qm.executable.TimeoutExecutable-class.html qm.executable.Executable.Spawn qm.executable.Executable-class.html#Spawn qm.executable.TimeoutExecutable.__Monitor qm.executable.TimeoutExecutable-class.html#__Monitor qm.executable.TimeoutExecutable.Run qm.executable.TimeoutExecutable-class.html#Run qm.executable.Executable._DoParent qm.executable.Executable-class.html#_DoParent qm.executable.Executable._InitializeParent qm.executable.Executable-class.html#_InitializeParent qm.executable.TimeoutExecutable._InitializeChild qm.executable.TimeoutExecutable-class.html#_InitializeChild qm.executable.TimeoutExecutable._HandleChild qm.executable.TimeoutExecutable-class.html#_HandleChild qm.executable.Executable.Kill qm.executable.Executable-class.html#Kill qm.executable.Executable._GetChildPID qm.executable.Executable-class.html#_GetChildPID qm.executable.TimeoutExecutable.__UseSeparateProcessGroupForChild qm.executable.TimeoutExecutable-class.html#__UseSeparateProcessGroupForChild qm.executable.TimeoutExecutable.__init__ qm.executable.TimeoutExecutable-class.html#__init__ qm.extension.Extension qm.extension.Extension-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.extension.Extension.__init__ qm.extension.Extension-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.kind qm.extension.Extension-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.extension.Extension.Type.__init__ qm.extension.Extension.Type-class.html#__init__ qm.external.DocumentTemplate.DT_HTML.HTML qm.external.DocumentTemplate.DT_HTML.HTML-class.html qm.external.DocumentTemplate.DT_HTML.HTML.management_interface qm.external.DocumentTemplate.DT_HTML.HTML-class.html#management_interface qm.external.DocumentTemplate.DT_String.String.initvars__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#initvars__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.SubTemplate qm.external.DocumentTemplate.DT_HTML.HTML-class.html#SubTemplate qm.external.DocumentTemplate.DT_HTML.HTML.__str__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#__str__ qm.external.DocumentTemplate.DT_HTML.HTML.manage qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage qm.external.DocumentTemplate.DT_HTML.HTML.manage_editDocument qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_editDocument qm.external.DocumentTemplate.DT_HTML.HTML.parseTag qm.external.DocumentTemplate.DT_HTML.HTML-class.html#parseTag qm.external.DocumentTemplate.DT_String.String.parse qm.external.DocumentTemplate.DT_String.String-class.html#parse qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_HTML.HTML.manage__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage__roles__ qm.external.DocumentTemplate.DT_String.String.initvars qm.external.DocumentTemplate.DT_String.String-class.html#initvars qm.external.DocumentTemplate.DT_HTML.HTML.manage_editForm__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_editForm__roles__ qm.external.DocumentTemplate.DT_String.String.var__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#var__roles__ qm.external.DocumentTemplate.DT_String.String.parse_error qm.external.DocumentTemplate.DT_String.String-class.html#parse_error qm.external.DocumentTemplate.DT_String.String.id qm.external.DocumentTemplate.DT_String.String-class.html#id qm.external.DocumentTemplate.DT_String.String.__init__ qm.external.DocumentTemplate.DT_String.String-class.html#__init__ qm.external.DocumentTemplate.DT_String.String.func_code qm.external.DocumentTemplate.DT_String.String-class.html#func_code qm.external.DocumentTemplate.DT_String.String.setName__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#setName__roles__ qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.tagre qm.external.DocumentTemplate.DT_HTML.HTML-class.html#tagre qm.external.DocumentTemplate.DT_String.String.parse_close__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_close__roles__ qm.external.DocumentTemplate.DT_String.String.func_defaults__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.management_interface__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#management_interface__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.varExtra qm.external.DocumentTemplate.DT_HTML.HTML-class.html#varExtra qm.external.DocumentTemplate.DT_String.String.read_raw__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#read_raw__roles__ qm.external.DocumentTemplate.DT_String.String._parseTag qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag qm.external.DocumentTemplate.DT_String.String.munge__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#munge__roles__ qm.external.DocumentTemplate.DT_String.String.cook__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#cook__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.SubTemplate__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#SubTemplate__roles__ qm.external.DocumentTemplate.DT_String.String.__call__ qm.external.DocumentTemplate.DT_String.String-class.html#__call__ qm.external.DocumentTemplate.DT_String.String.parse__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse__roles__ qm.external.DocumentTemplate.DT_String.String.__getstate__ qm.external.DocumentTemplate.DT_String.String-class.html#__getstate__ qm.external.DocumentTemplate.DT_HTML.HTML.tagre__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#tagre__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.quotedHTML qm.external.DocumentTemplate.DT_HTML.HTML-class.html#quotedHTML qm.external.DocumentTemplate.DT_String.String.read__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#read__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.manage_editDocument__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_editDocument__roles__ qm.external.DocumentTemplate.DT_String.String.setName qm.external.DocumentTemplate.DT_String.String-class.html#setName qm.external.DocumentTemplate.DT_HTML.HTML.parseTag__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.read qm.external.DocumentTemplate.DT_String.String-class.html#read qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String.parse_close qm.external.DocumentTemplate.DT_String.String-class.html#parse_close qm.external.DocumentTemplate.DT_String.String.munge qm.external.DocumentTemplate.DT_String.String-class.html#munge qm.external.DocumentTemplate.DT_String.String.validate__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#validate__roles__ qm.external.DocumentTemplate.DT_String.String.var qm.external.DocumentTemplate.DT_String.String-class.html#var qm.external.DocumentTemplate.DT_String.String.parse_error__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_error__roles__ qm.external.DocumentTemplate.DT_String.String.cook qm.external.DocumentTemplate.DT_String.String-class.html#cook qm.external.DocumentTemplate.DT_String.String._parseTag__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.validate qm.external.DocumentTemplate.DT_String.String-class.html#validate qm.external.DocumentTemplate.DT_HTML.HTML.manage_edit__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_edit__roles__ qm.external.DocumentTemplate.DT_String.String.default__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#default__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.manage_edit qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_edit qm.external.DocumentTemplate.DT_String.String.isDocTemp qm.external.DocumentTemplate.DT_String.String-class.html#isDocTemp qm.external.DocumentTemplate.DT_String.String.parse_block qm.external.DocumentTemplate.DT_String.String-class.html#parse_block qm.external.DocumentTemplate.DT_String.String.commands qm.external.DocumentTemplate.DT_String.String-class.html#commands qm.external.DocumentTemplate.DT_String.String.name qm.external.DocumentTemplate.DT_String.String-class.html#name qm.external.DocumentTemplate.DT_String.String.default qm.external.DocumentTemplate.DT_String.String-class.html#default qm.external.DocumentTemplate.DT_String.String.skip_eol qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol qm.external.DocumentTemplate.DT_String.String.skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String.read_raw qm.external.DocumentTemplate.DT_String.String-class.html#read_raw qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String.parse_block__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_block__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.manage_editForm qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_editForm qm.external.DocumentTemplate.DT_String.String.func_defaults qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults qm.external.DocumentTemplate.DT_HTML.HTML.errQuote__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#errQuote__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.quotedHTML__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#quotedHTML__roles__ qm.external.DocumentTemplate.DT_String.String.shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String.commands__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#commands__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.errQuote qm.external.DocumentTemplate.DT_HTML.HTML-class.html#errQuote qm.external.DocumentTemplate.DT_String.String.shared_globals qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals qm.external.DocumentTemplate.DT_HTML.HTML.varExtra__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#varExtra__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLDefault qm.external.DocumentTemplate.DT_HTML.HTMLDefault-class.html qm.external.DocumentTemplate.DT_HTML.HTML.management_interface qm.external.DocumentTemplate.DT_HTML.HTML-class.html#management_interface qm.external.DocumentTemplate.DT_String.String.initvars__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#initvars__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.varExtra qm.external.DocumentTemplate.DT_HTML.HTML-class.html#varExtra qm.external.DocumentTemplate.DT_HTML.HTML.__str__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#__str__ qm.external.DocumentTemplate.DT_HTML.HTML.manage qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage qm.external.DocumentTemplate.DT_HTML.HTML.manage_editDocument qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_editDocument qm.external.DocumentTemplate.DT_HTML.HTMLDefault.manage_edit__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLDefault-class.html#manage_edit__roles__ qm.external.DocumentTemplate.DT_String.String.parse qm.external.DocumentTemplate.DT_String.String-class.html#parse qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_HTML.HTMLDefault.copy_class__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLDefault-class.html#copy_class__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.manage__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage__roles__ qm.external.DocumentTemplate.DT_String.String.initvars qm.external.DocumentTemplate.DT_String.String-class.html#initvars qm.external.DocumentTemplate.DT_HTML.HTML.manage_editForm__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_editForm__roles__ qm.external.DocumentTemplate.DT_String.String.var__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#var__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLDefault.copy_class qm.external.DocumentTemplate.DT_HTML.HTML-class.html qm.external.DocumentTemplate.DT_String.String.parse_error qm.external.DocumentTemplate.DT_String.String-class.html#parse_error qm.external.DocumentTemplate.DT_String.String.id qm.external.DocumentTemplate.DT_String.String-class.html#id qm.external.DocumentTemplate.DT_String.String.__init__ qm.external.DocumentTemplate.DT_String.String-class.html#__init__ qm.external.DocumentTemplate.DT_String.String.func_code qm.external.DocumentTemplate.DT_String.String-class.html#func_code qm.external.DocumentTemplate.DT_String.String.setName__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#setName__roles__ qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.tagre qm.external.DocumentTemplate.DT_HTML.HTML-class.html#tagre qm.external.DocumentTemplate.DT_String.String.parse_close__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_close__roles__ qm.external.DocumentTemplate.DT_String.String.func_defaults__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.management_interface__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#management_interface__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.SubTemplate qm.external.DocumentTemplate.DT_HTML.HTML-class.html#SubTemplate qm.external.DocumentTemplate.DT_String.String.read_raw__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#read_raw__roles__ qm.external.DocumentTemplate.DT_String.String._parseTag qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag qm.external.DocumentTemplate.DT_String.String.munge__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#munge__roles__ qm.external.DocumentTemplate.DT_String.String.cook__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#cook__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.SubTemplate__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#SubTemplate__roles__ qm.external.DocumentTemplate.DT_String.String.__call__ qm.external.DocumentTemplate.DT_String.String-class.html#__call__ qm.external.DocumentTemplate.DT_String.String.parse__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse__roles__ qm.external.DocumentTemplate.DT_String.String.__getstate__ qm.external.DocumentTemplate.DT_String.String-class.html#__getstate__ qm.external.DocumentTemplate.DT_HTML.HTML.tagre__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#tagre__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.quotedHTML qm.external.DocumentTemplate.DT_HTML.HTML-class.html#quotedHTML qm.external.DocumentTemplate.DT_String.String.read__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#read__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.manage_editDocument__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_editDocument__roles__ qm.external.DocumentTemplate.DT_String.String.setName qm.external.DocumentTemplate.DT_String.String-class.html#setName qm.external.DocumentTemplate.DT_HTML.HTML.parseTag__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.read qm.external.DocumentTemplate.DT_String.String-class.html#read qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String.parse_close qm.external.DocumentTemplate.DT_String.String-class.html#parse_close qm.external.DocumentTemplate.DT_String.String.munge qm.external.DocumentTemplate.DT_String.String-class.html#munge qm.external.DocumentTemplate.DT_String.String.validate__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#validate__roles__ qm.external.DocumentTemplate.DT_String.String.var qm.external.DocumentTemplate.DT_String.String-class.html#var qm.external.DocumentTemplate.DT_String.String.parse_error__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_error__roles__ qm.external.DocumentTemplate.DT_String.String.cook qm.external.DocumentTemplate.DT_String.String-class.html#cook qm.external.DocumentTemplate.DT_String.String._parseTag__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.validate qm.external.DocumentTemplate.DT_String.String-class.html#validate qm.external.DocumentTemplate.DT_HTML.HTML.parseTag qm.external.DocumentTemplate.DT_HTML.HTML-class.html#parseTag qm.external.DocumentTemplate.DT_String.String.default__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#default__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLDefault.manage_edit qm.external.DocumentTemplate.DT_HTML.HTMLDefault-class.html#manage_edit qm.external.DocumentTemplate.DT_String.String.isDocTemp qm.external.DocumentTemplate.DT_String.String-class.html#isDocTemp qm.external.DocumentTemplate.DT_String.String.parse_block qm.external.DocumentTemplate.DT_String.String-class.html#parse_block qm.external.DocumentTemplate.DT_String.String.commands qm.external.DocumentTemplate.DT_String.String-class.html#commands qm.external.DocumentTemplate.DT_String.String.name qm.external.DocumentTemplate.DT_String.String-class.html#name qm.external.DocumentTemplate.DT_String.String.default qm.external.DocumentTemplate.DT_String.String-class.html#default qm.external.DocumentTemplate.DT_String.String.skip_eol qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol qm.external.DocumentTemplate.DT_String.String.skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String.read_raw qm.external.DocumentTemplate.DT_String.String-class.html#read_raw qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String.parse_block__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_block__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.manage_editForm qm.external.DocumentTemplate.DT_HTML.HTML-class.html#manage_editForm qm.external.DocumentTemplate.DT_String.String.func_defaults qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults qm.external.DocumentTemplate.DT_HTML.HTML.errQuote__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#errQuote__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.quotedHTML__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#quotedHTML__roles__ qm.external.DocumentTemplate.DT_String.String.shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String.commands__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#commands__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.errQuote qm.external.DocumentTemplate.DT_HTML.HTML-class.html#errQuote qm.external.DocumentTemplate.DT_String.String.shared_globals qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals qm.external.DocumentTemplate.DT_HTML.HTML.varExtra__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#varExtra__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html qm.external.DocumentTemplate.DT_HTML.HTML.management_interface qm.external.DocumentTemplate.DT_HTML.HTML-class.html#management_interface qm.external.DocumentTemplate.DT_String.String.initvars__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#initvars__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.varExtra qm.external.DocumentTemplate.DT_HTML.HTML-class.html#varExtra qm.external.DocumentTemplate.DT_HTML.HTML.__str__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#__str__ qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage_editDocument qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage_editDocument qm.external.DocumentTemplate.DT_String.String.parse_block qm.external.DocumentTemplate.DT_String.String-class.html#parse_block qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage_edit__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage_edit__roles__ qm.external.DocumentTemplate.DT_String.String.parse qm.external.DocumentTemplate.DT_String.String-class.html#parse qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage__roles__ qm.external.DocumentTemplate.DT_String.String.initvars qm.external.DocumentTemplate.DT_String.String-class.html#initvars qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage_editForm__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage_editForm__roles__ qm.external.DocumentTemplate.DT_String.String.var__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#var__roles__ qm.external.DocumentTemplate.DT_String.String.parse_error qm.external.DocumentTemplate.DT_String.String-class.html#parse_error qm.external.DocumentTemplate.DT_String.String.id qm.external.DocumentTemplate.DT_String.String-class.html#id qm.external.DocumentTemplate.DT_String.FileMixin.__init__ qm.external.DocumentTemplate.DT_String.FileMixin-class.html#__init__ qm.external.DocumentTemplate.DT_String.String.func_code qm.external.DocumentTemplate.DT_String.String-class.html#func_code qm.external.DocumentTemplate.DT_String.String.setName__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#setName__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage_default__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage_default__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.tagre qm.external.DocumentTemplate.DT_HTML.HTML-class.html#tagre qm.external.DocumentTemplate.DT_String.String.parse_close__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_close__roles__ qm.external.DocumentTemplate.DT_String.String.func_defaults__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.management_interface__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#management_interface__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.SubTemplate qm.external.DocumentTemplate.DT_HTML.HTML-class.html#SubTemplate qm.external.DocumentTemplate.DT_String.String._parseTag qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag qm.external.DocumentTemplate.DT_HTML.HTML.varExtra__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#varExtra__roles__ qm.external.DocumentTemplate.DT_String.String.munge__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#munge__roles__ qm.external.DocumentTemplate.DT_String.String.cook__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#cook__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.SubTemplate__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#SubTemplate__roles__ qm.external.DocumentTemplate.DT_String.String.__call__ qm.external.DocumentTemplate.DT_String.String-class.html#__call__ qm.external.DocumentTemplate.DT_String.String.parse__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse__roles__ qm.external.DocumentTemplate.DT_String.String.__getstate__ qm.external.DocumentTemplate.DT_String.String-class.html#__getstate__ qm.external.DocumentTemplate.DT_String.FileMixin.edited_source qm.external.DocumentTemplate.DT_String.FileMixin-class.html#edited_source qm.external.DocumentTemplate.DT_HTML.HTML.quotedHTML qm.external.DocumentTemplate.DT_HTML.HTML-class.html#quotedHTML qm.external.DocumentTemplate.DT_String.String.commands__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#commands__roles__ qm.external.DocumentTemplate.DT_String.String.skip_eol qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol qm.external.DocumentTemplate.DT_String.String.read__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#read__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage_editDocument__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage_editDocument__roles__ qm.external.DocumentTemplate.DT_String.String.setName qm.external.DocumentTemplate.DT_String.String-class.html#setName qm.external.DocumentTemplate.DT_HTML.HTML.parseTag__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.read qm.external.DocumentTemplate.DT_String.String-class.html#read qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String.parse_close qm.external.DocumentTemplate.DT_String.String-class.html#parse_close qm.external.DocumentTemplate.DT_String.String.munge qm.external.DocumentTemplate.DT_String.String-class.html#munge qm.external.DocumentTemplate.DT_String.FileMixin.read_raw qm.external.DocumentTemplate.DT_String.FileMixin-class.html#read_raw qm.external.DocumentTemplate.DT_String.String.var qm.external.DocumentTemplate.DT_String.String-class.html#var qm.external.DocumentTemplate.DT_HTML.HTML.tagre__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#tagre__roles__ qm.external.DocumentTemplate.DT_String.String.cook qm.external.DocumentTemplate.DT_String.String-class.html#cook qm.external.DocumentTemplate.DT_String.String._parseTag__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.validate qm.external.DocumentTemplate.DT_String.String-class.html#validate qm.external.DocumentTemplate.DT_HTML.HTML.parseTag qm.external.DocumentTemplate.DT_HTML.HTML-class.html#parseTag qm.external.DocumentTemplate.DT_String.String.default__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#default__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage_edit qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage_edit qm.external.DocumentTemplate.DT_String.String.isDocTemp qm.external.DocumentTemplate.DT_String.String-class.html#isDocTemp qm.external.DocumentTemplate.DT_String.String.validate__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#validate__roles__ qm.external.DocumentTemplate.DT_String.String.commands qm.external.DocumentTemplate.DT_String.String-class.html#commands qm.external.DocumentTemplate.DT_String.String.name qm.external.DocumentTemplate.DT_String.String-class.html#name qm.external.DocumentTemplate.DT_String.String.default qm.external.DocumentTemplate.DT_String.String-class.html#default qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage_default qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage_default qm.external.DocumentTemplate.DT_String.String.skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String.parse_block__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_block__roles__ qm.external.DocumentTemplate.DT_HTML.HTMLFile.manage_editForm qm.external.DocumentTemplate.DT_HTML.HTMLFile-class.html#manage_editForm qm.external.DocumentTemplate.DT_String.String.func_defaults qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults qm.external.DocumentTemplate.DT_HTML.HTML.errQuote__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#errQuote__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.quotedHTML__roles__ qm.external.DocumentTemplate.DT_HTML.HTML-class.html#quotedHTML__roles__ qm.external.DocumentTemplate.DT_String.String.shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String.parse_error__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_error__roles__ qm.external.DocumentTemplate.DT_HTML.HTML.errQuote qm.external.DocumentTemplate.DT_HTML.HTML-class.html#errQuote qm.external.DocumentTemplate.DT_String.String.shared_globals qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals qm.external.DocumentTemplate.DT_String.FileMixin.read_raw__roles__ qm.external.DocumentTemplate.DT_String.FileMixin-class.html#read_raw__roles__ qm.external.DocumentTemplate.DT_HTML.dtml_re_class qm.external.DocumentTemplate.DT_HTML.dtml_re_class-class.html qm.external.DocumentTemplate.DT_HTML.dtml_re_class.start qm.external.DocumentTemplate.DT_HTML.dtml_re_class-class.html#start qm.external.DocumentTemplate.DT_HTML.dtml_re_class.search qm.external.DocumentTemplate.DT_HTML.dtml_re_class-class.html#search qm.external.DocumentTemplate.DT_HTML.dtml_re_class.group qm.external.DocumentTemplate.DT_HTML.dtml_re_class-class.html#group qm.external.DocumentTemplate.DT_If.Else qm.external.DocumentTemplate.DT_If.Else-class.html qm.external.DocumentTemplate.DT_If.Else.name qm.external.DocumentTemplate.DT_If.Else-class.html#name qm.external.DocumentTemplate.DT_If.Unless.__init__ qm.external.DocumentTemplate.DT_If.Unless-class.html#__init__ qm.external.DocumentTemplate.DT_If.Unless.blockContinuations qm.external.DocumentTemplate.DT_If.Unless-class.html#blockContinuations qm.external.DocumentTemplate.DT_If.If qm.external.DocumentTemplate.DT_If.If-class.html qm.external.DocumentTemplate.DT_If.If.expr qm.external.DocumentTemplate.DT_If.If-class.html#expr qm.external.DocumentTemplate.DT_If.If.elses qm.external.DocumentTemplate.DT_If.If-class.html#elses qm.external.DocumentTemplate.DT_If.If.name qm.external.DocumentTemplate.DT_If.If-class.html#name qm.external.DocumentTemplate.DT_If.If.__init__ qm.external.DocumentTemplate.DT_If.If-class.html#__init__ qm.external.DocumentTemplate.DT_If.If.blockContinuations qm.external.DocumentTemplate.DT_If.If-class.html#blockContinuations qm.external.DocumentTemplate.DT_If.Unless qm.external.DocumentTemplate.DT_If.Unless-class.html qm.external.DocumentTemplate.DT_If.Unless.name qm.external.DocumentTemplate.DT_If.Unless-class.html#name qm.external.DocumentTemplate.DT_If.Unless.__init__ qm.external.DocumentTemplate.DT_If.Unless-class.html#__init__ qm.external.DocumentTemplate.DT_If.Unless.blockContinuations qm.external.DocumentTemplate.DT_If.Unless-class.html#blockContinuations qm.external.DocumentTemplate.DT_In.InClass qm.external.DocumentTemplate.DT_In.InClass-class.html qm.external.DocumentTemplate.DT_In.InClass.sort qm.external.DocumentTemplate.DT_In.InClass-class.html#sort qm.external.DocumentTemplate.DT_In.InClass.sort_sequence qm.external.DocumentTemplate.DT_In.InClass-class.html#sort_sequence qm.external.DocumentTemplate.DT_In.InClass.reverse qm.external.DocumentTemplate.DT_In.InClass-class.html#reverse qm.external.DocumentTemplate.DT_In.InClass.sort_expr qm.external.DocumentTemplate.DT_In.InClass-class.html#sort_expr qm.external.DocumentTemplate.DT_In.InClass.expr qm.external.DocumentTemplate.DT_In.InClass-class.html#expr qm.external.DocumentTemplate.DT_In.InClass.start_name_re qm.external.DocumentTemplate.DT_In.InClass-class.html#start_name_re qm.external.DocumentTemplate.DT_In.InClass.reverse_expr qm.external.DocumentTemplate.DT_In.InClass-class.html#reverse_expr qm.external.DocumentTemplate.DT_In.InClass.mapping qm.external.DocumentTemplate.DT_In.InClass-class.html#mapping qm.external.DocumentTemplate.DT_In.InClass.reverse_sequence qm.external.DocumentTemplate.DT_In.InClass-class.html#reverse_sequence qm.external.DocumentTemplate.DT_In.InClass.batch qm.external.DocumentTemplate.DT_In.InClass-class.html#batch qm.external.DocumentTemplate.DT_In.InClass.renderwob qm.external.DocumentTemplate.DT_In.InClass-class.html#renderwob qm.external.DocumentTemplate.DT_In.InClass.elses qm.external.DocumentTemplate.DT_In.InClass-class.html#elses qm.external.DocumentTemplate.DT_In.InClass.renderwb qm.external.DocumentTemplate.DT_In.InClass-class.html#renderwb qm.external.DocumentTemplate.DT_In.InClass.__init__ qm.external.DocumentTemplate.DT_In.InClass-class.html#__init__ qm.external.DocumentTemplate.DT_In.InFactory qm.external.DocumentTemplate.DT_In.InFactory-class.html qm.external.DocumentTemplate.DT_In.InFactory.__call__ qm.external.DocumentTemplate.DT_In.InFactory-class.html#__call__ qm.external.DocumentTemplate.DT_In.InFactory.name qm.external.DocumentTemplate.DT_In.InFactory-class.html#name qm.external.DocumentTemplate.DT_In.InFactory.blockContinuations qm.external.DocumentTemplate.DT_In.InFactory-class.html#blockContinuations qm.external.DocumentTemplate.DT_InSV.sequence_variables qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html qm.external.DocumentTemplate.DT_InSV.sequence_variables.letter qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#letter qm.external.DocumentTemplate.DT_InSV.sequence_variables.number qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#number qm.external.DocumentTemplate.DT_InSV.sequence_variables.statistic_names qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#statistic_names qm.external.DocumentTemplate.DT_InSV.sequence_variables.special_prefixes qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#special_prefixes qm.external.DocumentTemplate.DT_InSV.sequence_variables.query qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#query qm.external.DocumentTemplate.DT_InSV.sequence_variables.odd qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#odd qm.external.DocumentTemplate.DT_InSV.sequence_variables.__init__ qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#__init__ qm.external.DocumentTemplate.DT_InSV.sequence_variables.even qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#even qm.external.DocumentTemplate.DT_InSV.sequence_variables.statistics qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#statistics qm.external.DocumentTemplate.DT_InSV.sequence_variables.length qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#length qm.external.DocumentTemplate.DT_InSV.sequence_variables.Letter qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#Letter qm.external.DocumentTemplate.DT_InSV.sequence_variables.__len__ qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#__len__ qm.external.DocumentTemplate.DT_InSV.sequence_variables.next_batches qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#next_batches qm.external.DocumentTemplate.DT_InSV.sequence_variables.__getitem__ qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#__getitem__ qm.external.DocumentTemplate.DT_InSV.sequence_variables.Roman qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#Roman qm.external.DocumentTemplate.DT_InSV.sequence_variables.key qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#key qm.external.DocumentTemplate.DT_InSV.sequence_variables.last qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#last qm.external.DocumentTemplate.DT_InSV.sequence_variables.value qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#value qm.external.DocumentTemplate.DT_InSV.sequence_variables.n qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#n qm.external.DocumentTemplate.DT_InSV.sequence_variables.item qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#item qm.external.DocumentTemplate.DT_InSV.sequence_variables.roman qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#roman qm.external.DocumentTemplate.DT_InSV.sequence_variables.previous_batches qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#previous_batches qm.external.DocumentTemplate.DT_InSV.sequence_variables.first qm.external.DocumentTemplate.DT_InSV.sequence_variables-class.html#first qm.external.DocumentTemplate.DT_Let.Let qm.external.DocumentTemplate.DT_Let.Let-class.html qm.external.DocumentTemplate.DT_Let.Let.__call__ qm.external.DocumentTemplate.DT_Let.Let-class.html#__call__ qm.external.DocumentTemplate.DT_Let.Let.__init__ qm.external.DocumentTemplate.DT_Let.Let-class.html#__init__ qm.external.DocumentTemplate.DT_Let.Let.name qm.external.DocumentTemplate.DT_Let.Let-class.html#name qm.external.DocumentTemplate.DT_Let.Let.render qm.external.DocumentTemplate.DT_Let.Let-class.html#render qm.external.DocumentTemplate.DT_Let.Let.blockContinuations qm.external.DocumentTemplate.DT_Let.Let-class.html#blockContinuations qm.external.DocumentTemplate.DT_Raise.Raise qm.external.DocumentTemplate.DT_Raise.Raise-class.html qm.external.DocumentTemplate.DT_Raise.Raise.name qm.external.DocumentTemplate.DT_Raise.Raise-class.html#name qm.external.DocumentTemplate.DT_Raise.Raise.render qm.external.DocumentTemplate.DT_Raise.Raise-class.html#render qm.external.DocumentTemplate.DT_Raise.Raise.expr qm.external.DocumentTemplate.DT_Raise.Raise-class.html#expr qm.external.DocumentTemplate.DT_Raise.Raise.blockContinuations qm.external.DocumentTemplate.DT_Raise.Raise-class.html#blockContinuations qm.external.DocumentTemplate.DT_Raise.Raise.__call__ qm.external.DocumentTemplate.DT_Raise.Raise-class.html#__call__ qm.external.DocumentTemplate.DT_Raise.Raise.__init__ qm.external.DocumentTemplate.DT_Raise.Raise-class.html#__init__ qm.external.DocumentTemplate.DT_Return.DTReturn qm.external.DocumentTemplate.DT_Return.DTReturn-class.html qm.external.DocumentTemplate.DT_Return.DTReturn.__init__ qm.external.DocumentTemplate.DT_Return.DTReturn-class.html#__init__ qm.external.DocumentTemplate.DT_Return.ReturnTag qm.external.DocumentTemplate.DT_Return.ReturnTag-class.html qm.external.DocumentTemplate.DT_Return.ReturnTag.__call__ qm.external.DocumentTemplate.DT_Return.ReturnTag-class.html#__call__ qm.external.DocumentTemplate.DT_Return.ReturnTag.expr qm.external.DocumentTemplate.DT_Return.ReturnTag-class.html#expr qm.external.DocumentTemplate.DT_Return.ReturnTag.__init__ qm.external.DocumentTemplate.DT_Return.ReturnTag-class.html#__init__ qm.external.DocumentTemplate.DT_Return.ReturnTag.name qm.external.DocumentTemplate.DT_Return.ReturnTag-class.html#name qm.external.DocumentTemplate.DT_Return.ReturnTag.render qm.external.DocumentTemplate.DT_Return.ReturnTag-class.html#render qm.external.DocumentTemplate.DT_String.File qm.external.DocumentTemplate.DT_String.File-class.html qm.external.DocumentTemplate.DT_String.String.initvars__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#initvars__roles__ qm.external.DocumentTemplate.DT_String.FileMixin.read_raw qm.external.DocumentTemplate.DT_String.FileMixin-class.html#read_raw qm.external.DocumentTemplate.DT_String.String.__str__ qm.external.DocumentTemplate.DT_String.String-class.html#__str__ qm.external.DocumentTemplate.DT_String.String.parseTag qm.external.DocumentTemplate.DT_String.String-class.html#parseTag qm.external.DocumentTemplate.DT_String.String.parse qm.external.DocumentTemplate.DT_String.String-class.html#parse qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_String.String.initvars qm.external.DocumentTemplate.DT_String.String-class.html#initvars qm.external.DocumentTemplate.DT_String.String.isDocTemp qm.external.DocumentTemplate.DT_String.String-class.html#isDocTemp qm.external.DocumentTemplate.DT_String.String.var__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#var__roles__ qm.external.DocumentTemplate.DT_String.String.parse_error qm.external.DocumentTemplate.DT_String.String-class.html#parse_error qm.external.DocumentTemplate.DT_String.String.id qm.external.DocumentTemplate.DT_String.String-class.html#id qm.external.DocumentTemplate.DT_String.FileMixin.__init__ qm.external.DocumentTemplate.DT_String.FileMixin-class.html#__init__ qm.external.DocumentTemplate.DT_String.String.func_code qm.external.DocumentTemplate.DT_String.String-class.html#func_code qm.external.DocumentTemplate.DT_String.String.setName__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#setName__roles__ qm.external.DocumentTemplate.DT_String.String.tagre qm.external.DocumentTemplate.DT_String.String-class.html#tagre qm.external.DocumentTemplate.DT_String.String.parse_close__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_close__roles__ qm.external.DocumentTemplate.DT_String.String.func_defaults__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults__roles__ qm.external.DocumentTemplate.DT_String.String.SubTemplate qm.external.DocumentTemplate.DT_String.String-class.html#SubTemplate qm.external.DocumentTemplate.DT_String.String._parseTag qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag qm.external.DocumentTemplate.DT_String.String.munge__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#munge__roles__ qm.external.DocumentTemplate.DT_String.String.cook__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#cook__roles__ qm.external.DocumentTemplate.DT_String.String.SubTemplate__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#SubTemplate__roles__ qm.external.DocumentTemplate.DT_String.String.__call__ qm.external.DocumentTemplate.DT_String.String-class.html#__call__ qm.external.DocumentTemplate.DT_String.String.parse__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse__roles__ qm.external.DocumentTemplate.DT_String.String.__getstate__ qm.external.DocumentTemplate.DT_String.String-class.html#__getstate__ qm.external.DocumentTemplate.DT_String.FileMixin.edited_source qm.external.DocumentTemplate.DT_String.FileMixin-class.html#edited_source qm.external.DocumentTemplate.DT_String.String.read__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#read__roles__ qm.external.DocumentTemplate.DT_String.String.skip_eol qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol qm.external.DocumentTemplate.DT_String.String.setName qm.external.DocumentTemplate.DT_String.String-class.html#setName qm.external.DocumentTemplate.DT_String.String.parseTag__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.read qm.external.DocumentTemplate.DT_String.String-class.html#read qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String.parse_close qm.external.DocumentTemplate.DT_String.String-class.html#parse_close qm.external.DocumentTemplate.DT_String.String.munge qm.external.DocumentTemplate.DT_String.String-class.html#munge qm.external.DocumentTemplate.DT_String.String.validate__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#validate__roles__ qm.external.DocumentTemplate.DT_String.String.var qm.external.DocumentTemplate.DT_String.String-class.html#var qm.external.DocumentTemplate.DT_String.String.parse_error__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_error__roles__ qm.external.DocumentTemplate.DT_String.String.cook qm.external.DocumentTemplate.DT_String.String-class.html#cook qm.external.DocumentTemplate.DT_String.String._parseTag__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.validate qm.external.DocumentTemplate.DT_String.String-class.html#validate qm.external.DocumentTemplate.DT_String.File.manage_edit__roles__ qm.external.DocumentTemplate.DT_String.File-class.html#manage_edit__roles__ qm.external.DocumentTemplate.DT_String.String.default__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#default__roles__ qm.external.DocumentTemplate.DT_String.File.manage_edit qm.external.DocumentTemplate.DT_String.File-class.html#manage_edit qm.external.DocumentTemplate.DT_String.String.varExtra qm.external.DocumentTemplate.DT_String.String-class.html#varExtra qm.external.DocumentTemplate.DT_String.String.parse_block qm.external.DocumentTemplate.DT_String.String-class.html#parse_block qm.external.DocumentTemplate.DT_String.String.commands qm.external.DocumentTemplate.DT_String.String-class.html#commands qm.external.DocumentTemplate.DT_String.String.errQuote qm.external.DocumentTemplate.DT_String.String-class.html#errQuote qm.external.DocumentTemplate.DT_String.String.name qm.external.DocumentTemplate.DT_String.String-class.html#name qm.external.DocumentTemplate.DT_String.String.default qm.external.DocumentTemplate.DT_String.String-class.html#default qm.external.DocumentTemplate.DT_String.String.tagre__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#tagre__roles__ qm.external.DocumentTemplate.DT_String.String.skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String.parse_block__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_block__roles__ qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_String.String.func_defaults qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults qm.external.DocumentTemplate.DT_String.String.errQuote__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#errQuote__roles__ qm.external.DocumentTemplate.DT_String.String.shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String.commands__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#commands__roles__ qm.external.DocumentTemplate.DT_String.String.varExtra__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#varExtra__roles__ qm.external.DocumentTemplate.DT_String.String.shared_globals qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals qm.external.DocumentTemplate.DT_String.FileMixin.read_raw__roles__ qm.external.DocumentTemplate.DT_String.FileMixin-class.html#read_raw__roles__ qm.external.DocumentTemplate.DT_String.FileMixin qm.external.DocumentTemplate.DT_String.FileMixin-class.html qm.external.DocumentTemplate.DT_String.FileMixin.read_raw__roles__ qm.external.DocumentTemplate.DT_String.FileMixin-class.html#read_raw__roles__ qm.external.DocumentTemplate.DT_String.FileMixin.edited_source qm.external.DocumentTemplate.DT_String.FileMixin-class.html#edited_source qm.external.DocumentTemplate.DT_String.FileMixin.__init__ qm.external.DocumentTemplate.DT_String.FileMixin-class.html#__init__ qm.external.DocumentTemplate.DT_String.FileMixin.read_raw qm.external.DocumentTemplate.DT_String.FileMixin-class.html#read_raw qm.external.DocumentTemplate.DT_String.String qm.external.DocumentTemplate.DT_String.String-class.html qm.external.DocumentTemplate.DT_String.String.parse_block__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_block__roles__ qm.external.DocumentTemplate.DT_String.String.initvars__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#initvars__roles__ qm.external.DocumentTemplate.DT_String.String.__call__ qm.external.DocumentTemplate.DT_String.String-class.html#__call__ qm.external.DocumentTemplate.DT_String.String.SubTemplate qm.external.DocumentTemplate.DT_String.String-class.html#SubTemplate qm.external.DocumentTemplate.DT_String.String.__str__ qm.external.DocumentTemplate.DT_String.String-class.html#__str__ qm.external.DocumentTemplate.DT_String.String.parseTag qm.external.DocumentTemplate.DT_String.String-class.html#parseTag qm.external.DocumentTemplate.DT_String.String.parse qm.external.DocumentTemplate.DT_String.String-class.html#parse qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender qm.external.DocumentTemplate.DT_String.String.initvars qm.external.DocumentTemplate.DT_String.String-class.html#initvars qm.external.DocumentTemplate.DT_String.String.isDocTemp qm.external.DocumentTemplate.DT_String.String-class.html#isDocTemp qm.external.DocumentTemplate.DT_String.String.var__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#var__roles__ qm.external.DocumentTemplate.DT_String.String.parse_error qm.external.DocumentTemplate.DT_String.String-class.html#parse_error qm.external.DocumentTemplate.DT_String.String.id qm.external.DocumentTemplate.DT_String.String-class.html#id qm.external.DocumentTemplate.DT_String.String.__init__ qm.external.DocumentTemplate.DT_String.String-class.html#__init__ qm.external.DocumentTemplate.DT_String.String.func_code qm.external.DocumentTemplate.DT_String.String-class.html#func_code qm.external.DocumentTemplate.DT_String.String.setName__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#setName__roles__ qm.external.DocumentTemplate.DT_String.String.tagre qm.external.DocumentTemplate.DT_String.String-class.html#tagre qm.external.DocumentTemplate.DT_String.String.parse_close__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_close__roles__ qm.external.DocumentTemplate.DT_String.String.func_defaults__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults__roles__ qm.external.DocumentTemplate.DT_String.String.varExtra qm.external.DocumentTemplate.DT_String.String-class.html#varExtra qm.external.DocumentTemplate.DT_String.String._parseTag qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag qm.external.DocumentTemplate.DT_String.String.varExtra__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#varExtra__roles__ qm.external.DocumentTemplate.DT_String.String.munge__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#munge__roles__ qm.external.DocumentTemplate.DT_String.String.default__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#default__roles__ qm.external.DocumentTemplate.DT_String.String.SubTemplate__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#SubTemplate__roles__ qm.external.DocumentTemplate.DT_String.String.var qm.external.DocumentTemplate.DT_String.String-class.html#var qm.external.DocumentTemplate.DT_String.String.parse__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse__roles__ qm.external.DocumentTemplate.DT_String.String.__getstate__ qm.external.DocumentTemplate.DT_String.String-class.html#__getstate__ qm.external.DocumentTemplate.DT_String.String.tagre__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#tagre__roles__ qm.external.DocumentTemplate.DT_String.String.setName qm.external.DocumentTemplate.DT_String.String-class.html#setName qm.external.DocumentTemplate.DT_String.String.parseTag__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.read qm.external.DocumentTemplate.DT_String.String-class.html#read qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_beforeRender__roles__ qm.external.DocumentTemplate.DT_String.String.parse_close qm.external.DocumentTemplate.DT_String.String-class.html#parse_close qm.external.DocumentTemplate.DT_String.String.munge qm.external.DocumentTemplate.DT_String.String-class.html#munge qm.external.DocumentTemplate.DT_String.String.validate__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#validate__roles__ qm.external.DocumentTemplate.DT_String.String.read_raw qm.external.DocumentTemplate.DT_String.String-class.html#read_raw qm.external.DocumentTemplate.DT_String.String.parse_error__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#parse_error__roles__ qm.external.DocumentTemplate.DT_String.String.cook qm.external.DocumentTemplate.DT_String.String-class.html#cook qm.external.DocumentTemplate.DT_String.String._parseTag__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#_parseTag__roles__ qm.external.DocumentTemplate.DT_String.String.validate qm.external.DocumentTemplate.DT_String.String-class.html#validate qm.external.DocumentTemplate.DT_String.String.manage_edit__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#manage_edit__roles__ qm.external.DocumentTemplate.DT_String.String.cook__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#cook__roles__ qm.external.DocumentTemplate.DT_String.String.manage_edit qm.external.DocumentTemplate.DT_String.String-class.html#manage_edit qm.external.DocumentTemplate.DT_String.String.parse_block qm.external.DocumentTemplate.DT_String.String-class.html#parse_block qm.external.DocumentTemplate.DT_String.String.commands qm.external.DocumentTemplate.DT_String.String-class.html#commands qm.external.DocumentTemplate.DT_String.String.name qm.external.DocumentTemplate.DT_String.String-class.html#name qm.external.DocumentTemplate.DT_String.String.default qm.external.DocumentTemplate.DT_String.String-class.html#default qm.external.DocumentTemplate.DT_String.String.skip_eol qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol qm.external.DocumentTemplate.DT_String.String.skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#skip_eol__roles__ qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender qm.external.DocumentTemplate.DT_String.String.read__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#read__roles__ qm.external.DocumentTemplate.DT_String.String.ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#ZDocumentTemplate_afterRender__roles__ qm.external.DocumentTemplate.DT_String.String.func_defaults qm.external.DocumentTemplate.DT_String.String-class.html#func_defaults qm.external.DocumentTemplate.DT_String.String.errQuote__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#errQuote__roles__ qm.external.DocumentTemplate.DT_String.String.shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals__roles__ qm.external.DocumentTemplate.DT_String.String.commands__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#commands__roles__ qm.external.DocumentTemplate.DT_String.String.errQuote qm.external.DocumentTemplate.DT_String.String-class.html#errQuote qm.external.DocumentTemplate.DT_String.String.shared_globals qm.external.DocumentTemplate.DT_String.String-class.html#shared_globals qm.external.DocumentTemplate.DT_String.String.read_raw__roles__ qm.external.DocumentTemplate.DT_String.String-class.html#read_raw__roles__ qm.external.DocumentTemplate.DT_Try.Try qm.external.DocumentTemplate.DT_Try.Try-class.html qm.external.DocumentTemplate.DT_Try.Try.find_handler qm.external.DocumentTemplate.DT_Try.Try-class.html#find_handler qm.external.DocumentTemplate.DT_Try.Try.name qm.external.DocumentTemplate.DT_Try.Try-class.html#name qm.external.DocumentTemplate.DT_Try.Try.render qm.external.DocumentTemplate.DT_Try.Try-class.html#render qm.external.DocumentTemplate.DT_Try.Try.match_base qm.external.DocumentTemplate.DT_Try.Try-class.html#match_base qm.external.DocumentTemplate.DT_Try.Try.render_try_finally qm.external.DocumentTemplate.DT_Try.Try-class.html#render_try_finally qm.external.DocumentTemplate.DT_Try.Try.elseBlock qm.external.DocumentTemplate.DT_Try.Try-class.html#elseBlock qm.external.DocumentTemplate.DT_Try.Try.finallyBlock qm.external.DocumentTemplate.DT_Try.Try-class.html#finallyBlock qm.external.DocumentTemplate.DT_Try.Try.blockContinuations qm.external.DocumentTemplate.DT_Try.Try-class.html#blockContinuations qm.external.DocumentTemplate.DT_Try.Try.__call__ qm.external.DocumentTemplate.DT_Try.Try-class.html#__call__ qm.external.DocumentTemplate.DT_Try.Try.__init__ qm.external.DocumentTemplate.DT_Try.Try-class.html#__init__ qm.external.DocumentTemplate.DT_Try.Try.render_try_except qm.external.DocumentTemplate.DT_Try.Try-class.html#render_try_except qm.external.DocumentTemplate.DT_Util.Eval qm.external.DocumentTemplate.DT_Util.Eval-class.html qm.external.DocumentTemplate.VSEval.Eval.__call__ qm.external.DocumentTemplate.VSEval.Eval-class.html#__call__ qm.external.DocumentTemplate.VSEval.Eval.__init__ qm.external.DocumentTemplate.VSEval.Eval-class.html#__init__ qm.external.DocumentTemplate.DT_Util.Eval.eval qm.external.DocumentTemplate.DT_Util.Eval-class.html#eval qm.external.DocumentTemplate.DT_Var.Call qm.external.DocumentTemplate.DT_Var.Call-class.html qm.external.DocumentTemplate.DT_Var.Call.expr qm.external.DocumentTemplate.DT_Var.Call-class.html#expr qm.external.DocumentTemplate.DT_Var.Call.name qm.external.DocumentTemplate.DT_Var.Call-class.html#name qm.external.DocumentTemplate.DT_Var.Call.__init__ qm.external.DocumentTemplate.DT_Var.Call-class.html#__init__ qm.external.DocumentTemplate.DT_Var.Comment qm.external.DocumentTemplate.DT_Var.Comment-class.html qm.external.DocumentTemplate.DT_Var.Comment.__call__ qm.external.DocumentTemplate.DT_Var.Comment-class.html#__call__ qm.external.DocumentTemplate.DT_Var.Comment.__init__ qm.external.DocumentTemplate.DT_Var.Comment-class.html#__init__ qm.external.DocumentTemplate.DT_Var.Comment.name qm.external.DocumentTemplate.DT_Var.Comment-class.html#name qm.external.DocumentTemplate.DT_Var.Comment.render qm.external.DocumentTemplate.DT_Var.Comment-class.html#render qm.external.DocumentTemplate.DT_Var.Comment.blockContinuations qm.external.DocumentTemplate.DT_Var.Comment-class.html#blockContinuations qm.external.DocumentTemplate.DT_Var.Var qm.external.DocumentTemplate.DT_Var.Var-class.html qm.external.DocumentTemplate.DT_Var.Var.__call__ qm.external.DocumentTemplate.DT_Var.Var-class.html#__call__ qm.external.DocumentTemplate.DT_Var.Var.expr qm.external.DocumentTemplate.DT_Var.Var-class.html#expr qm.external.DocumentTemplate.DT_Var.Var.__init__ qm.external.DocumentTemplate.DT_Var.Var-class.html#__init__ qm.external.DocumentTemplate.DT_Var.Var.name qm.external.DocumentTemplate.DT_Var.Var-class.html#name qm.external.DocumentTemplate.DT_Var.Var.render qm.external.DocumentTemplate.DT_Var.Var-class.html#render qm.external.DocumentTemplate.DT_With.With qm.external.DocumentTemplate.DT_With.With-class.html qm.external.DocumentTemplate.DT_With.With.name qm.external.DocumentTemplate.DT_With.With-class.html#name qm.external.DocumentTemplate.DT_With.With.render qm.external.DocumentTemplate.DT_With.With-class.html#render qm.external.DocumentTemplate.DT_With.With.mapping qm.external.DocumentTemplate.DT_With.With-class.html#mapping qm.external.DocumentTemplate.DT_With.With.blockContinuations qm.external.DocumentTemplate.DT_With.With-class.html#blockContinuations qm.external.DocumentTemplate.DT_With.With.only qm.external.DocumentTemplate.DT_With.With-class.html#only qm.external.DocumentTemplate.DT_With.With.__call__ qm.external.DocumentTemplate.DT_With.With-class.html#__call__ qm.external.DocumentTemplate.DT_With.With.__init__ qm.external.DocumentTemplate.DT_With.With-class.html#__init__ qm.external.DocumentTemplate.VSEval.Eval qm.external.DocumentTemplate.VSEval.Eval-class.html qm.external.DocumentTemplate.VSEval.Eval.__call__ qm.external.DocumentTemplate.VSEval.Eval-class.html#__call__ qm.external.DocumentTemplate.VSEval.Eval.__init__ qm.external.DocumentTemplate.VSEval.Eval-class.html#__init__ qm.external.DocumentTemplate.VSEval.Eval.eval qm.external.DocumentTemplate.VSEval.Eval-class.html#eval qm.external.DocumentTemplate.pDocumentTemplate.DictInstance qm.external.DocumentTemplate.pDocumentTemplate.DictInstance-class.html qm.external.DocumentTemplate.pDocumentTemplate.DictInstance.__init__ qm.external.DocumentTemplate.pDocumentTemplate.DictInstance-class.html#__init__ qm.external.DocumentTemplate.pDocumentTemplate.DictInstance.__getattr__ qm.external.DocumentTemplate.pDocumentTemplate.DictInstance-class.html#__getattr__ qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict-class.html qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict.__getitem__ qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict-class.html#__getitem__ qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict.keys qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict-class.html#keys qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict.has_key qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict-class.html#has_key qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict.__repr__ qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict-class.html#__repr__ qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict.validate qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict-class.html#validate qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict.__init__ qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict-class.html#__init__ qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping-class.html qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping.keys qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping-class.html#keys qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping.push qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping-class.html#push qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping.__init__ qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping-class.html#__init__ qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping.pop qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping-class.html#pop qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping.__getitem__ qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping-class.html#__getitem__ qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict._push qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#_push qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.render qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#render qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.int int-class.html qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.pow qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#pow qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.random random-module.html qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict._pop qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#_pop qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.has_key qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#has_key qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.divmod qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#divmod qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.__init__ qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#__init__ qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.min qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#min qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.hex qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#hex qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.getattr qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#getattr qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.chr qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#chr qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.abs qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#abs qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.__call__ qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#__call__ qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.oct qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#oct qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.math math-module.html qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.None qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#None qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.float float-class.html qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.hash qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#hash qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.string string-module.html qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.__getitem__ qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#__getitem__ qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.max qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#max qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.len qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#len qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.test qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#test qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.ord qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#ord qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.hasattr qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#hasattr qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.attr qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#attr qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.level qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#level qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.range qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#range qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.getitem qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#getitem qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.str str-class.html qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.namespace qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#namespace qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict.round qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.html#round qm.fields.AttachmentField qm.fields.AttachmentField-class.html qm.fields.AttachmentField.ParseFormValue qm.fields.AttachmentField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.AttachmentField.FormatValueAsText qm.fields.AttachmentField-class.html#FormatValueAsText qm.fields.AttachmentField.GetHelp qm.fields.AttachmentField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.AttachmentField.__init__ qm.fields.AttachmentField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.AttachmentField.MakeDomNodeForValue qm.fields.AttachmentField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.AttachmentField.download_url qm.fields.AttachmentField-class.html#download_url qm.fields.AttachmentField.FormatValueAsHtml qm.fields.AttachmentField-class.html#FormatValueAsHtml qm.fields.AttachmentField.Validate qm.fields.AttachmentField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.AttachmentField.GetValueFromDomNode qm.fields.AttachmentField-class.html#GetValueFromDomNode qm.fields.AttachmentField.upload_url qm.fields.AttachmentField-class.html#upload_url qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.AttachmentField.GetHtmlHelp qm.fields.AttachmentField-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.AttachmentField._FormatSummary qm.fields.AttachmentField-class.html#_FormatSummary qm.fields.Field.ParseTextValue qm.fields.Field-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.BooleanField qm.fields.BooleanField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.EnumerationField.GetHelp qm.fields.EnumerationField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.BooleanField.__init__ qm.fields.BooleanField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.EnumerationField.MakeDomNodeForValue qm.fields.EnumerationField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.ChoiceField.FormatValueAsHtml qm.fields.ChoiceField-class.html#FormatValueAsHtml qm.fields.BooleanField.Validate qm.fields.BooleanField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.EnumerationField.GetValueFromDomNode qm.fields.EnumerationField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.EnumerationField.GetItems qm.fields.EnumerationField-class.html#GetItems qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.ChoiceField qm.fields.ChoiceField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.TextField.GetHelp qm.fields.TextField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.TextField.__init__ qm.fields.TextField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.TextField.MakeDomNodeForValue qm.fields.TextField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.ChoiceField.FormatValueAsHtml qm.fields.ChoiceField-class.html#FormatValueAsHtml qm.fields.ChoiceField.Validate qm.fields.ChoiceField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.TextField.GetValueFromDomNode qm.fields.TextField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.ChoiceField.GetItems qm.fields.ChoiceField-class.html#GetItems qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.DictionaryField qm.fields.DictionaryField-class.html qm.fields.DictionaryField.ParseFormValue qm.fields.DictionaryField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.Field.FormatValueAsText qm.fields.Field-class.html#FormatValueAsText qm.fields.DictionaryField.GetHelp qm.fields.DictionaryField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.DictionaryField.__init__ qm.fields.DictionaryField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.DictionaryField.MakeDomNodeForValue qm.fields.DictionaryField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.DictionaryField.FormatValueAsHtml qm.fields.DictionaryField-class.html#FormatValueAsHtml qm.fields.DictionaryField.Validate qm.fields.DictionaryField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.DictionaryField.GetValueField qm.fields.DictionaryField-class.html#GetValueField qm.fields.DictionaryField.GetValueFromDomNode qm.fields.DictionaryField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.DictionaryField.GetKeyField qm.fields.DictionaryField-class.html#GetKeyField qm.fields.DictionaryField.ParseTextValue qm.fields.DictionaryField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.EnumerationField qm.fields.EnumerationField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.EnumerationField.GetHelp qm.fields.EnumerationField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.EnumerationField.__init__ qm.fields.EnumerationField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.EnumerationField.MakeDomNodeForValue qm.fields.EnumerationField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.ChoiceField.FormatValueAsHtml qm.fields.ChoiceField-class.html#FormatValueAsHtml qm.fields.ChoiceField.Validate qm.fields.ChoiceField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.EnumerationField.GetValueFromDomNode qm.fields.EnumerationField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.EnumerationField.GetItems qm.fields.EnumerationField-class.html#GetItems qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.Field qm.fields.Field-class.html qm.fields.Field.ParseFormValue qm.fields.Field-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.Field.FormatValueAsText qm.fields.Field-class.html#FormatValueAsText qm.fields.Field.GetHelp qm.fields.Field-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.Field.__init__ qm.fields.Field-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.Field.MakeDomNodeForValue qm.fields.Field-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.Field.FormatValueAsHtml qm.fields.Field-class.html#FormatValueAsHtml qm.fields.Field.Validate qm.fields.Field-class.html#Validate qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.Field.GetValueFromDomNode qm.fields.Field-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.Field.ParseTextValue qm.fields.Field-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.IntegerField qm.fields.IntegerField-class.html qm.fields.Field.ParseFormValue qm.fields.Field-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.IntegerField.FormatValueAsText qm.fields.IntegerField-class.html#FormatValueAsText qm.fields.IntegerField.GetHelp qm.fields.IntegerField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.IntegerField.__init__ qm.fields.IntegerField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.IntegerField.MakeDomNodeForValue qm.fields.IntegerField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.IntegerField.FormatValueAsHtml qm.fields.IntegerField-class.html#FormatValueAsHtml qm.fields.IntegerField.Validate qm.fields.IntegerField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.IntegerField.GetValueFromDomNode qm.fields.IntegerField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.IntegerField.ParseTextValue qm.fields.IntegerField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.PythonField qm.fields.PythonField-class.html qm.fields.Field.ParseFormValue qm.fields.Field-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.Field.FormatValueAsText qm.fields.Field-class.html#FormatValueAsText qm.fields.Field.GetHelp qm.fields.Field-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.PythonField.__init__ qm.fields.PythonField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.Field.MakeDomNodeForValue qm.fields.Field-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.Field.FormatValueAsHtml qm.fields.Field-class.html#FormatValueAsHtml qm.fields.Field.Validate qm.fields.Field-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.Field.GetValueFromDomNode qm.fields.Field-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.Field.ParseTextValue qm.fields.Field-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.SetField qm.fields.SetField-class.html qm.fields.SetField.ParseFormValue qm.fields.SetField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.SetField.FormatValueAsText qm.fields.SetField-class.html#FormatValueAsText qm.fields.SetField.GetHelp qm.fields.SetField-class.html#GetHelp qm.fields.SetField.GetSubfields qm.fields.SetField-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.SetField.__init__ qm.fields.SetField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.SetField.MakeDomNodeForValue qm.fields.SetField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.SetField.FormatValueAsHtml qm.fields.SetField-class.html#FormatValueAsHtml qm.fields.SetField.Validate qm.fields.SetField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.SetField.GetValueFromDomNode qm.fields.SetField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.SetField.GetHtmlHelp qm.fields.SetField-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.SetField.ParseTextValue qm.fields.SetField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.TextField qm.fields.TextField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.TextField.GetHelp qm.fields.TextField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.TextField.__init__ qm.fields.TextField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.TextField.MakeDomNodeForValue qm.fields.TextField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.TextField.FormatValueAsHtml qm.fields.TextField-class.html#FormatValueAsHtml qm.fields.TextField.Validate qm.fields.TextField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.TextField.GetValueFromDomNode qm.fields.TextField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.TimeField qm.fields.TimeField-class.html qm.fields.Field.ParseFormValue qm.fields.Field-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TimeField.FormatValueAsText qm.fields.TimeField-class.html#FormatValueAsText qm.fields.TimeField.GetHelp qm.fields.TimeField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.TimeField.__init__ qm.fields.TimeField-class.html#__init__ qm.fields.TimeField.GetDefaultValue qm.fields.TimeField-class.html#GetDefaultValue qm.fields.IntegerField.MakeDomNodeForValue qm.fields.IntegerField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.TimeField.FormatValueAsHtml qm.fields.TimeField-class.html#FormatValueAsHtml qm.fields.IntegerField.Validate qm.fields.IntegerField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.IntegerField.GetValueFromDomNode qm.fields.IntegerField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TimeField.ParseTextValue qm.fields.TimeField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.TupleField qm.fields.TupleField-class.html qm.fields.TupleField.ParseFormValue qm.fields.TupleField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.Field.FormatValueAsText qm.fields.Field-class.html#FormatValueAsText qm.fields.TupleField.GetHelp qm.fields.TupleField-class.html#GetHelp qm.fields.TupleField.GetSubfields qm.fields.TupleField-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.TupleField.__init__ qm.fields.TupleField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.TupleField.MakeDomNodeForValue qm.fields.TupleField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.TupleField.FormatValueAsHtml qm.fields.TupleField-class.html#FormatValueAsHtml qm.fields.TupleField.Validate qm.fields.TupleField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.TupleField.GetValueFromDomNode qm.fields.TupleField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.Field.ParseTextValue qm.fields.Field-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.fields.UploadAttachmentPage qm.fields.UploadAttachmentPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.fields.UploadAttachmentPage.__init__ qm.fields.UploadAttachmentPage-class.html#__init__ qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.web.DtmlPage.GenerateHtmlHeader qm.web.DtmlPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.web.DtmlPage.GetMainPageUrl qm.web.DtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.GenerateStartBody qm.web.DtmlPage-class.html#GenerateStartBody qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.fields.UploadAttachmentPage.MakeSubmitUrl qm.fields.UploadAttachmentPage-class.html#MakeSubmitUrl qm.host.Host qm.host.Host-class.html qm.host.Host.Executable qm.host.Host.Executable-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.host.Host.__init__ qm.host.Host-class.html#__init__ qm.host.Host.Run qm.host.Host-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.host.Host.DownloadFile qm.host.Host-class.html#DownloadFile qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.host.Host.DeleteFile qm.host.Host-class.html#DeleteFile qm.host.Host.UploadFile qm.host.Host-class.html#UploadFile qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.host.Host.kind qm.host.Host-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.host.Host.UploadAndRun qm.host.Host-class.html#UploadAndRun qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.host.Host.Executable qm.host.Host.Executable-class.html qm.host.Host.Executable._StderrPipe qm.host.Host.Executable-class.html#_StderrPipe qm.host.Host.Executable qm.host.Host.Executable-class.html qm.host.Host.Executable._StderrPipe qm.host.Host.Executable-class.html#_StderrPipe qm.label.Label qm.label.Label-class.html qm.label.Label.SplitLeft qm.label.Label-class.html#SplitLeft qm.label.Label.Join qm.label.Label-class.html#Join qm.label.Label.IsValid qm.label.Label-class.html#IsValid qm.label.Label.Basename qm.label.Label-class.html#Basename qm.label.Label.Split qm.label.Label-class.html#Split qm.label.Label.Dirname qm.label.Label-class.html#Dirname qm.label.Label.__str__ qm.label.Label-class.html#__str__ qm.label.Label.__init__ qm.label.Label-class.html#__init__ qm.platform.MailError qm.platform.MailError-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.platform_unix.SignalException qm.platform_unix.SignalException-class.html qm.platform_unix.SignalException.GetSignalNumber qm.platform_unix.SignalException-class.html#GetSignalNumber qm.platform_unix.SignalException.__init__ qm.platform_unix.SignalException-class.html#__init__ qm.platform_win32.SignalException qm.platform_win32.SignalException-class.html qm.platform_win32.SignalException.__init__ qm.platform_win32.SignalException-class.html#__init__ qm.structured_text.Formatter qm.structured_text.Formatter-class.html qm.structured_text.HtmlFormatter qm.structured_text.HtmlFormatter-class.html qm.structured_text.HtmlFormatter.WriteText qm.structured_text.HtmlFormatter-class.html#WriteText qm.structured_text.HtmlFormatter.End qm.structured_text.HtmlFormatter-class.html#End qm.structured_text.HtmlFormatter.EndItem qm.structured_text.HtmlFormatter-class.html#EndItem qm.structured_text.HtmlFormatter.StartStyle qm.structured_text.HtmlFormatter-class.html#StartStyle qm.structured_text.HtmlFormatter.StartItem qm.structured_text.HtmlFormatter-class.html#StartItem qm.structured_text.HtmlFormatter.EndStyle qm.structured_text.HtmlFormatter-class.html#EndStyle qm.structured_text.HtmlFormatter.EndList qm.structured_text.HtmlFormatter-class.html#EndList qm.structured_text.HtmlFormatter.StartLink qm.structured_text.HtmlFormatter-class.html#StartLink qm.structured_text.HtmlFormatter.__start_list_tags qm.structured_text.HtmlFormatter-class.html#__start_list_tags qm.structured_text.HtmlFormatter.__start_item_tags qm.structured_text.HtmlFormatter-class.html#__start_item_tags qm.structured_text.HtmlFormatter.__end_list_tags qm.structured_text.HtmlFormatter-class.html#__end_list_tags qm.structured_text.HtmlFormatter.EndLink qm.structured_text.HtmlFormatter-class.html#EndLink qm.structured_text.HtmlFormatter.__init__ qm.structured_text.HtmlFormatter-class.html#__init__ qm.structured_text.HtmlFormatter.__end_item_tags qm.structured_text.HtmlFormatter-class.html#__end_item_tags qm.structured_text.HtmlFormatter.__end_style_tags qm.structured_text.HtmlFormatter-class.html#__end_style_tags qm.structured_text.HtmlFormatter.FinishDefinedTerm qm.structured_text.HtmlFormatter-class.html#FinishDefinedTerm qm.structured_text.HtmlFormatter.__Write qm.structured_text.HtmlFormatter-class.html#__Write qm.structured_text.HtmlFormatter.__start_style_tags qm.structured_text.HtmlFormatter-class.html#__start_style_tags qm.structured_text.HtmlFormatter.StartList qm.structured_text.HtmlFormatter-class.html#StartList qm.structured_text.StructuredTextProcessor qm.structured_text.StructuredTextProcessor-class.html qm.structured_text.StructuredTextProcessor.__emph_regex qm.structured_text.StructuredTextProcessor-class.html#__emph_regex qm.structured_text.StructuredTextProcessor.__PushType qm.structured_text.StructuredTextProcessor-class.html#__PushType qm.structured_text.StructuredTextProcessor.NormalizeSpaces qm.structured_text.StructuredTextProcessor-class.html#NormalizeSpaces qm.structured_text.StructuredTextProcessor.End qm.structured_text.StructuredTextProcessor-class.html#End qm.structured_text.StructuredTextProcessor.__non_nestable_types qm.structured_text.StructuredTextProcessor-class.html#__non_nestable_types qm.structured_text.StructuredTextProcessor.__PopType qm.structured_text.StructuredTextProcessor-class.html#__PopType qm.structured_text.StructuredTextProcessor.__link_regex qm.structured_text.StructuredTextProcessor-class.html#__link_regex qm.structured_text.StructuredTextProcessor.__underline_regex qm.structured_text.StructuredTextProcessor-class.html#__underline_regex qm.structured_text.StructuredTextProcessor.__WriteText qm.structured_text.StructuredTextProcessor-class.html#__WriteText qm.structured_text.StructuredTextProcessor.__collapse_regex qm.structured_text.StructuredTextProcessor-class.html#__collapse_regex qm.structured_text.StructuredTextProcessor.__strong_regex qm.structured_text.StructuredTextProcessor-class.html#__strong_regex qm.structured_text.StructuredTextProcessor.__indent_regex qm.structured_text.StructuredTextProcessor-class.html#__indent_regex qm.structured_text.StructuredTextProcessor.__SetType qm.structured_text.StructuredTextProcessor-class.html#__SetType qm.structured_text.StructuredTextProcessor.__literal_regex qm.structured_text.StructuredTextProcessor-class.html#__literal_regex qm.structured_text.StructuredTextProcessor.__definition_regex qm.structured_text.StructuredTextProcessor-class.html#__definition_regex qm.structured_text.StructuredTextProcessor.__call__ qm.structured_text.StructuredTextProcessor-class.html#__call__ qm.structured_text.StructuredTextProcessor.__bullet_regex qm.structured_text.StructuredTextProcessor-class.html#__bullet_regex qm.structured_text.StructuredTextProcessor.__punctuation qm.structured_text.StructuredTextProcessor-class.html#__punctuation qm.structured_text.StructuredTextProcessor.__link_footnote_regex qm.structured_text.StructuredTextProcessor-class.html#__link_footnote_regex qm.structured_text.StructuredTextProcessor.__sequence_regex qm.structured_text.StructuredTextProcessor-class.html#__sequence_regex qm.structured_text.StructuredTextProcessor.__init__ qm.structured_text.StructuredTextProcessor-class.html#__init__ qm.structured_text.TextFormatter qm.structured_text.TextFormatter-class.html qm.structured_text.TextFormatter.WriteText qm.structured_text.TextFormatter-class.html#WriteText qm.structured_text.TextFormatter.End qm.structured_text.TextFormatter-class.html#End qm.structured_text.TextFormatter.EndItem qm.structured_text.TextFormatter-class.html#EndItem qm.structured_text.TextFormatter.StartStyle qm.structured_text.TextFormatter-class.html#StartStyle qm.structured_text.TextFormatter.StartItem qm.structured_text.TextFormatter-class.html#StartItem qm.structured_text.TextFormatter.__NextLine qm.structured_text.TextFormatter-class.html#__NextLine qm.structured_text.TextFormatter.__style_markers qm.structured_text.TextFormatter-class.html#__style_markers qm.structured_text.TextFormatter.EndList qm.structured_text.TextFormatter-class.html#EndList qm.structured_text.TextFormatter.StartLink qm.structured_text.TextFormatter-class.html#StartLink qm.structured_text.TextFormatter.FinishDefinedTerm qm.structured_text.TextFormatter-class.html#FinishDefinedTerm qm.structured_text.TextFormatter.EndLink qm.structured_text.TextFormatter-class.html#EndLink qm.structured_text.TextFormatter.StartList qm.structured_text.TextFormatter-class.html#StartList qm.structured_text.TextFormatter.__Write qm.structured_text.TextFormatter-class.html#__Write qm.structured_text.TextFormatter.EndStyle qm.structured_text.TextFormatter-class.html#EndStyle qm.structured_text.TextFormatter.__init__ qm.structured_text.TextFormatter-class.html#__init__ qm.structured_text.TextFormatter.__IndentTo qm.structured_text.TextFormatter-class.html#__IndentTo qm.temporary_directory.TemporaryDirectory qm.temporary_directory.TemporaryDirectory-class.html qm.temporary_directory.TemporaryDirectory.__del__ qm.temporary_directory.TemporaryDirectory-class.html#__del__ qm.temporary_directory.TemporaryDirectory.__RemoveDirectory qm.temporary_directory.TemporaryDirectory-class.html#__RemoveDirectory qm.temporary_directory.TemporaryDirectory.__init__ qm.temporary_directory.TemporaryDirectory-class.html#__init__ qm.temporary_directory.TemporaryDirectory.GetPath qm.temporary_directory.TemporaryDirectory-class.html#GetPath qm.temporary_directory.TemporaryDirectory.Remove qm.temporary_directory.TemporaryDirectory-class.html#Remove qm.test.base.CouldNotLoadExtensionError qm.test.base.CouldNotLoadExtensionError-class.html qm.test.base.CouldNotLoadExtensionError.__init__ qm.test.base.CouldNotLoadExtensionError-class.html#__init__ qm.test.classes.command.ExecTest qm.test.classes.command.ExecTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.command.ExecTestBase.ValidateOutput qm.test.classes.command.ExecTestBase-class.html#ValidateOutput qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.command.ExecTestBase.MakeEnvironment qm.test.classes.command.ExecTestBase-class.html#MakeEnvironment qm.test.classes.command.ExecTestBase.RunProgram qm.test.classes.command.ExecTestBase-class.html#RunProgram qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.command.ExecTest.Run qm.test.classes.command.ExecTest-class.html#Run qm.test.classes.command.ExecTest._allow_arg_names_matching_class_vars qm.test.classes.command.ExecTest-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.command.ExecTest.arguments qm.test.classes.command.ExecTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.command.ExecTestBase qm.test.classes.command.ExecTestBase-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.command.ExecTestBase.ValidateOutput qm.test.classes.command.ExecTestBase-class.html#ValidateOutput qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.command.ExecTestBase.MakeEnvironment qm.test.classes.command.ExecTestBase-class.html#MakeEnvironment qm.test.classes.command.ExecTestBase.RunProgram qm.test.classes.command.ExecTestBase-class.html#RunProgram qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.classes.command.ExecTestBase.arguments qm.test.classes.command.ExecTestBase-class.html#arguments qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.classes.command.ExecTestBase.__CompareText qm.test.classes.command.ExecTestBase-class.html#__CompareText qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.command.ShellCommandTest qm.test.classes.command.ShellCommandTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.command.ExecTestBase.ValidateOutput qm.test.classes.command.ExecTestBase-class.html#ValidateOutput qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.command.ExecTestBase.MakeEnvironment qm.test.classes.command.ExecTestBase-class.html#MakeEnvironment qm.test.classes.command.ExecTestBase.RunProgram qm.test.classes.command.ExecTestBase-class.html#RunProgram qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.command.ShellCommandTest.Run qm.test.classes.command.ShellCommandTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.command.ShellCommandTest.arguments qm.test.classes.command.ShellCommandTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.command.ShellScriptTest qm.test.classes.command.ShellScriptTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.command.ExecTestBase.ValidateOutput qm.test.classes.command.ExecTestBase-class.html#ValidateOutput qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.command.ExecTestBase.MakeEnvironment qm.test.classes.command.ExecTestBase-class.html#MakeEnvironment qm.test.classes.command.ExecTestBase.RunProgram qm.test.classes.command.ExecTestBase-class.html#RunProgram qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.command.ShellScriptTest.Run qm.test.classes.command.ShellScriptTest-class.html#Run qm.test.classes.command.ShellScriptTest._allow_arg_names_matching_class_vars qm.test.classes.command.ShellScriptTest-class.html#_allow_arg_names_matching_class_vars qm.test.classes.command.ShellScriptTest._GetShell qm.test.classes.command.ShellScriptTest-class.html#_GetShell qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.command.ShellScriptTest.arguments qm.test.classes.command.ShellScriptTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.command_host.CommandHost qm.test.classes.command_host.CommandHost-class.html qm.host.Host.Executable qm.host.Host.Executable-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.command_host.CommandHost.command_args qm.test.classes.command_host.CommandHost-class.html#command_args qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.command_host.CommandHost.Run qm.test.classes.command_host.CommandHost-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.command_host.CommandHost.command qm.test.classes.command_host.CommandHost-class.html#command qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.compilation_test.CompilationTest qm.test.classes.compilation_test.CompilationTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.compilation_test.CompilationTest._GetCompilationSteps qm.test.classes.compilation_test.CompilationTest-class.html#_GetCompilationSteps qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.classes.compilation_test.CompilationTest.ldflags qm.test.classes.compilation_test.CompilationTest-class.html#ldflags qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.classes.compilation_test.CompilationTest._GetCompiler qm.test.classes.compilation_test.CompilationTest-class.html#_GetCompiler qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.compilation_test.CompilationTest.executable qm.test.classes.compilation_test.CompilationTest-class.html#executable qm.test.classes.compilation_test.CompilationTest.Run qm.test.classes.compilation_test.CompilationTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.compilation_test.CompilationTest._IsExecutionRequired qm.test.classes.compilation_test.CompilationTest-class.html#_IsExecutionRequired qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.compilation_test.CompilationTest.source_files qm.test.classes.compilation_test.CompilationTest-class.html#source_files qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.classes.compilation_test.CompilationTest._CheckOutput qm.test.classes.compilation_test.CompilationTest-class.html#_CheckOutput qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.classes.compilation_test.CompilationTest._GetTarget qm.test.classes.compilation_test.CompilationTest-class.html#_GetTarget qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.classes.compilation_test.CompilationTest.execute qm.test.classes.compilation_test.CompilationTest-class.html#execute qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.compilation_test.CompilationTest.options qm.test.classes.compilation_test.CompilationTest-class.html#options qm.test.classes.compilation_test.CompiledResource qm.test.classes.compilation_test.CompiledResource-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.classes.compilation_test.CompiledResource.executable qm.test.classes.compilation_test.CompiledResource-class.html#executable qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.compilation_test.CompiledResource.CleanUp qm.test.classes.compilation_test.CompiledResource-class.html#CleanUp qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.compilation_test.CompiledResource.source_files qm.test.classes.compilation_test.CompiledResource-class.html#source_files qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.arguments qm.test.runnable.Runnable-class.html#arguments qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.resource.Resource.kind qm.test.resource.Resource-class.html#kind qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.classes.compilation_test.CompiledResource.SetUp qm.test.classes.compilation_test.CompiledResource-class.html#SetUp qm.test.classes.compilation_test.CompiledResource.options qm.test.classes.compilation_test.CompiledResource-class.html#options qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.test.classes.compilation_test.ExecutableTest qm.test.classes.compilation_test.ExecutableTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.compilation_test.ExecutableTest.Run qm.test.classes.compilation_test.ExecutableTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.classes.compilation_test.ExecutableTest.args qm.test.classes.compilation_test.ExecutableTest-class.html#args qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.compilation_test_database.CompilationTest qm.test.classes.compilation_test_database.CompilationTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.compilation_test_database.CompilationTest._GetCompilationSteps qm.test.classes.compilation_test_database.CompilationTest-class.html#_GetCompilationSteps qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.classes.compilation_test_database.CompilationTest.ldflags qm.test.classes.compilation_test_database.CompilationTest-class.html#ldflags qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.compilation_test_database.CompilationTest.executable qm.test.classes.compilation_test_database.CompilationTest-class.html#executable qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.compilation_test_database.CompilationTest.source_files qm.test.classes.compilation_test_database.CompilationTest-class.html#source_files qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.classes.compilation_test_database.CompilationTest.language qm.test.classes.compilation_test_database.CompilationTest-class.html#language qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.compilation_test_database.CompilationTest.options qm.test.classes.compilation_test_database.CompilationTest-class.html#options qm.test.classes.compilation_test_database.CompilationTestDatabase qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html qm.test.classes.compilation_test_database.CompilationTestDatabase.test_extensions qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#test_extensions qm.test.database.Database.GetAttachmentStore qm.test.database.Database-class.html#GetAttachmentStore qm.test.classes.compilation_test_database.CompilationTestDatabase._MakeTest qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#_MakeTest qm.test.database.Database.modifiable qm.test.database.Database-class.html#modifiable qm.test.database.Database.GetResourceClassNames qm.test.database.Database-class.html#GetResourceClassNames qm.test.database.Database.GetTest qm.test.database.Database-class.html#GetTest qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.compilation_test_database.CompilationTestDatabase.excluded_subdirs qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#excluded_subdirs qm.test.database.Database.HasTest qm.test.database.Database-class.html#HasTest qm.test.database.Database.GetSuite qm.test.database.Database-class.html#GetSuite qm.test.database.Database.SUITE qm.test.database.Database-class.html#SUITE qm.test.database.Database.GetExtensions qm.test.database.Database-class.html#GetExtensions qm.test.database.Database.IsValidLabel qm.test.database.Database-class.html#IsValidLabel qm.test.classes.compilation_test_database.CompilationTestDatabase.__init__ qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#__init__ qm.test.database.Database.GetResourceIds qm.test.database.Database-class.html#GetResourceIds qm.test.database.Database.RESOURCE qm.test.database.Database-class.html#RESOURCE qm.test.database.Database.WriteExtension qm.test.database.Database-class.html#WriteExtension qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.database.Database.JoinLabels qm.test.database.Database-class.html#JoinLabels qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.database.Database.GetResource qm.test.database.Database-class.html#GetResource qm.test.database.Database.label_class qm.test.database.Database-class.html#label_class qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.database.Database.ExpandIds qm.test.database.Database-class.html#ExpandIds qm.test.database.Database.SplitLabel qm.test.database.Database-class.html#SplitLabel qm.test.classes.compilation_test_database.CompilationTestDatabase.GetSubdirectories qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#GetSubdirectories qm.test.database.Database.arguments qm.test.database.Database-class.html#arguments qm.test.database.Database.GetConfigurationDirectory qm.test.database.Database-class.html#GetConfigurationDirectory qm.test.classes.compilation_test_database.CompilationTestDatabase.srcdir qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#srcdir qm.test.database.Database.GetTestIds qm.test.database.Database-class.html#GetTestIds qm.test.database.Database.GetClassPaths qm.test.database.Database-class.html#GetClassPaths qm.test.database.Database.HasResource qm.test.database.Database-class.html#HasResource qm.test.database.Database.GetTestClassNames qm.test.database.Database-class.html#GetTestClassNames qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.database.Database.RemoveExtension qm.test.database.Database-class.html#RemoveExtension qm.test.database.Database._argument_list qm.test.database.Database-class.html#_argument_list qm.test.database.Database.GetPath qm.test.database.Database-class.html#GetPath qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.database.Database.IsModifiable qm.test.database.Database-class.html#IsModifiable qm.test.classes.compilation_test_database.CompilationTestDatabase.GetIds qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#GetIds qm.test.database.Database.GetSuiteIds qm.test.database.Database-class.html#GetSuiteIds qm.test.classes.compilation_test_database.CompilationTestDatabase.GetExtension qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#GetExtension qm.test.database.Database.GetLabelComponents qm.test.database.Database-class.html#GetLabelComponents qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.database.Database.HasSuite qm.test.database.Database-class.html#HasSuite qm.test.database.Database._argument_dictionary qm.test.database.Database-class.html#_argument_dictionary qm.test.database.Database.kind qm.test.database.Database-class.html#kind qm.test.database.Database.ITEM_KINDS qm.test.database.Database-class.html#ITEM_KINDS qm.test.database.Database._item_exceptions qm.test.database.Database-class.html#_item_exceptions qm.test.classes.compilation_test_database.CompilationTestDatabase._is_generic_database qm.test.classes.compilation_test_database.CompilationTestDatabase-class.html#_is_generic_database qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.database.Database.GetItem qm.test.database.Database-class.html#GetItem qm.test.database.Database.SplitLabelLeft qm.test.database.Database-class.html#SplitLabelLeft qm.test.database.Database.TEST qm.test.database.Database-class.html#TEST qm.test.classes.compiler.Compiler qm.test.classes.compiler.Compiler-class.html qm.test.classes.compiler.Compiler._GetModeSwitches qm.test.classes.compiler.Compiler-class.html#_GetModeSwitches qm.test.classes.compiler.Compiler.SetOptions qm.test.classes.compiler.Compiler-class.html#SetOptions qm.test.classes.compiler.Compiler.modes qm.test.classes.compiler.Compiler-class.html#modes qm.test.classes.compiler.Compiler.GetObjectExtension qm.test.classes.compiler.Compiler-class.html#GetObjectExtension qm.test.classes.compiler.Compiler.ExecuteCommand qm.test.classes.compiler.Compiler-class.html#ExecuteCommand qm.test.classes.compiler.Compiler.GetPath qm.test.classes.compiler.Compiler-class.html#GetPath qm.test.classes.compiler.Compiler.GetExecutableExtension qm.test.classes.compiler.Compiler-class.html#GetExecutableExtension qm.test.classes.compiler.Compiler.Compile qm.test.classes.compiler.Compiler-class.html#Compile qm.test.classes.compiler.Compiler.MODE_ASSEMBLE qm.test.classes.compiler.Compiler-class.html#MODE_ASSEMBLE qm.test.classes.compiler.Compiler.GetCompilationCommand qm.test.classes.compiler.Compiler-class.html#GetCompilationCommand qm.test.classes.compiler.Compiler.MODE_LINK qm.test.classes.compiler.Compiler-class.html#MODE_LINK qm.test.classes.compiler.Compiler.MODE_COMPILE qm.test.classes.compiler.Compiler-class.html#MODE_COMPILE qm.test.classes.compiler.Compiler.MODE_PREPROCESS qm.test.classes.compiler.Compiler-class.html#MODE_PREPROCESS qm.test.classes.compiler.Compiler.SetLDFlags qm.test.classes.compiler.Compiler-class.html#SetLDFlags qm.test.classes.compiler.Compiler.GetOptions qm.test.classes.compiler.Compiler-class.html#GetOptions qm.test.classes.compiler.Compiler.ParseOutput qm.test.classes.compiler.Compiler-class.html#ParseOutput qm.test.classes.compiler.Compiler.__init__ qm.test.classes.compiler.Compiler-class.html#__init__ qm.test.classes.compiler.Compiler.GetLDFlags qm.test.classes.compiler.Compiler-class.html#GetLDFlags qm.test.classes.compiler.CompilerExecutable qm.test.classes.compiler.CompilerExecutable-class.html qm.test.classes.compiler.CompilerExecutable._StdinPipe qm.test.classes.compiler.CompilerExecutable-class.html#_StdinPipe qm.test.classes.compiler.CompilerExecutable._StderrPipe qm.test.classes.compiler.CompilerExecutable-class.html#_StderrPipe qm.test.classes.compiler.CompilerExecutable._InitializeChild qm.test.classes.compiler.CompilerExecutable-class.html#_InitializeChild qm.test.classes.compiler.Diagnostic qm.test.classes.compiler.Diagnostic-class.html qm.test.classes.compiler.Diagnostic.__str__ qm.test.classes.compiler.Diagnostic-class.html#__str__ qm.test.classes.compiler.Diagnostic.__init__ qm.test.classes.compiler.Diagnostic-class.html#__init__ qm.test.classes.compiler.EDG qm.test.classes.compiler.EDG-class.html qm.test.classes.compiler.Compiler.GetLDFlags qm.test.classes.compiler.Compiler-class.html#GetLDFlags qm.test.classes.compiler.Compiler.SetOptions qm.test.classes.compiler.Compiler-class.html#SetOptions qm.test.classes.compiler.Compiler.modes qm.test.classes.compiler.Compiler-class.html#modes qm.test.classes.compiler.Compiler.GetObjectExtension qm.test.classes.compiler.Compiler-class.html#GetObjectExtension qm.test.classes.compiler.Compiler.MODE_PREPROCESS qm.test.classes.compiler.Compiler-class.html#MODE_PREPROCESS qm.test.classes.compiler.Compiler.ExecuteCommand qm.test.classes.compiler.Compiler-class.html#ExecuteCommand qm.test.classes.compiler.Compiler.GetPath qm.test.classes.compiler.Compiler-class.html#GetPath qm.test.classes.compiler.Compiler._GetModeSwitches qm.test.classes.compiler.Compiler-class.html#_GetModeSwitches qm.test.classes.compiler.Compiler.MODE_ASSEMBLE qm.test.classes.compiler.Compiler-class.html#MODE_ASSEMBLE qm.test.classes.compiler.Compiler.MODE_LINK qm.test.classes.compiler.Compiler-class.html#MODE_LINK qm.test.classes.compiler.Compiler.__init__ qm.test.classes.compiler.Compiler-class.html#__init__ qm.test.classes.compiler.Compiler.MODE_COMPILE qm.test.classes.compiler.Compiler-class.html#MODE_COMPILE qm.test.classes.compiler.Compiler.Compile qm.test.classes.compiler.Compiler-class.html#Compile qm.test.classes.compiler.Compiler.GetCompilationCommand qm.test.classes.compiler.Compiler-class.html#GetCompilationCommand qm.test.classes.compiler.Compiler.SetLDFlags qm.test.classes.compiler.Compiler-class.html#SetLDFlags qm.test.classes.compiler.Compiler.GetOptions qm.test.classes.compiler.Compiler-class.html#GetOptions qm.test.classes.compiler.EDG.ParseOutput qm.test.classes.compiler.EDG-class.html#ParseOutput qm.test.classes.compiler.EDG.__diagnostic_regexp qm.test.classes.compiler.EDG-class.html#__diagnostic_regexp qm.test.classes.compiler.Compiler.GetExecutableExtension qm.test.classes.compiler.Compiler-class.html#GetExecutableExtension qm.test.classes.compiler.GCC qm.test.classes.compiler.GCC-class.html qm.test.classes.compiler.GCC._internal_error_regexp qm.test.classes.compiler.GCC-class.html#_internal_error_regexp qm.test.classes.compiler.Compiler._GetModeSwitches qm.test.classes.compiler.Compiler-class.html#_GetModeSwitches qm.test.classes.compiler.Compiler.MODE_ASSEMBLE qm.test.classes.compiler.Compiler-class.html#MODE_ASSEMBLE qm.test.classes.compiler.Compiler.MODE_LINK qm.test.classes.compiler.Compiler-class.html#MODE_LINK qm.test.classes.compiler.Compiler.GetCompilationCommand qm.test.classes.compiler.Compiler-class.html#GetCompilationCommand qm.test.classes.compiler.Compiler.__init__ qm.test.classes.compiler.Compiler-class.html#__init__ qm.test.classes.compiler.Compiler.GetLDFlags qm.test.classes.compiler.Compiler-class.html#GetLDFlags qm.test.classes.compiler.Compiler.GetObjectExtension qm.test.classes.compiler.Compiler-class.html#GetObjectExtension qm.test.classes.compiler.GCC._severity_regexps qm.test.classes.compiler.GCC-class.html#_severity_regexps qm.test.classes.compiler.GCC.MODE_PRECOMPILE qm.test.classes.compiler.GCC-class.html#MODE_PRECOMPILE qm.test.classes.compiler.Compiler.MODE_COMPILE qm.test.classes.compiler.Compiler-class.html#MODE_COMPILE qm.test.classes.compiler.Compiler.MODE_PREPROCESS qm.test.classes.compiler.Compiler-class.html#MODE_PREPROCESS qm.test.classes.compiler.Compiler.GetOptions qm.test.classes.compiler.Compiler-class.html#GetOptions qm.test.classes.compiler.GCC._severities qm.test.classes.compiler.GCC-class.html#_severities qm.test.classes.compiler.Compiler.GetPath qm.test.classes.compiler.Compiler-class.html#GetPath qm.test.classes.compiler.Compiler.Compile qm.test.classes.compiler.Compiler-class.html#Compile qm.test.classes.compiler.Compiler.SetLDFlags qm.test.classes.compiler.Compiler-class.html#SetLDFlags qm.test.classes.compiler.GCC.ParseOutput qm.test.classes.compiler.GCC-class.html#ParseOutput qm.test.classes.compiler.GCC.modes qm.test.classes.compiler.GCC-class.html#modes qm.test.classes.compiler.Compiler.GetExecutableExtension qm.test.classes.compiler.Compiler-class.html#GetExecutableExtension qm.test.classes.compiler.Compiler.ExecuteCommand qm.test.classes.compiler.Compiler-class.html#ExecuteCommand qm.test.classes.compiler.Compiler.SetOptions qm.test.classes.compiler.Compiler-class.html#SetOptions qm.test.classes.compiler.SourcePosition qm.test.classes.compiler.SourcePosition-class.html qm.test.classes.compiler.SourcePosition.__str__ qm.test.classes.compiler.SourcePosition-class.html#__str__ qm.test.classes.compiler.SourcePosition.__init__ qm.test.classes.compiler.SourcePosition-class.html#__init__ qm.test.classes.compiler_table.CompilerTable qm.test.classes.compiler_table.CompilerTable-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.compiler_table.CompilerTable.LANG_C qm.test.classes.compiler_table.CompilerTable-class.html#LANG_C qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.resource.Resource.CleanUp qm.test.resource.Resource-class.html#CleanUp qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.arguments qm.test.runnable.Runnable-class.html#arguments qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.resource.Resource.kind qm.test.resource.Resource-class.html#kind qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.classes.compiler_table.CompilerTable.SetUp qm.test.classes.compiler_table.CompilerTable-class.html#SetUp qm.test.classes.compiler_table.CompilerTable.LANG_CPLUSPLUS qm.test.classes.compiler_table.CompilerTable-class.html#LANG_CPLUSPLUS qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.test.classes.compiler_test.CompilationStep qm.test.classes.compiler_test.CompilationStep-class.html qm.test.classes.compiler_test.CompilationStep.__init__ qm.test.classes.compiler_test.CompilationStep-class.html#__init__ qm.test.classes.compiler_test.CompilerBase qm.test.classes.compiler_test.CompilerBase-class.html qm.test.classes.compiler_test.CompilerBase._RemoveDirectory qm.test.classes.compiler_test.CompilerBase-class.html#_RemoveDirectory qm.test.classes.compiler_test.CompilerBase._GetObjectFileName qm.test.classes.compiler_test.CompilerBase-class.html#_GetObjectFileName qm.test.classes.compiler_test.CompilerBase._MakeDirectory qm.test.classes.compiler_test.CompilerBase-class.html#_MakeDirectory qm.test.classes.compiler_test.CompilerBase._GetDirectory qm.test.classes.compiler_test.CompilerBase-class.html#_GetDirectory qm.test.classes.compiler_test.CompilerTest qm.test.classes.compiler_test.CompilerTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.compiler_test.CompilerBase._MakeDirectory qm.test.classes.compiler_test.CompilerBase-class.html#_MakeDirectory qm.test.classes.compiler_test.CompilerTest._GetCompilationSteps qm.test.classes.compiler_test.CompilerTest-class.html#_GetCompilationSteps qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.classes.compiler_test.CompilerTest._GetExecutableArguments qm.test.classes.compiler_test.CompilerTest-class.html#_GetExecutableArguments qm.test.classes.compiler_test.CompilerBase._GetObjectFileName qm.test.classes.compiler_test.CompilerBase-class.html#_GetObjectFileName qm.test.classes.compiler_test.CompilerTest._GetCompiler qm.test.classes.compiler_test.CompilerTest-class.html#_GetCompiler qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.classes.compiler_test.CompilerBase._GetDirectory qm.test.classes.compiler_test.CompilerBase-class.html#_GetDirectory qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.compiler_test.CompilerTest.Run qm.test.classes.compiler_test.CompilerTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.compiler_test.CompilerTest._IsExecutionRequired qm.test.classes.compiler_test.CompilerTest-class.html#_IsExecutionRequired qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.compiler_test.CompilerTest._MustExecutableExitSuccessfully qm.test.classes.compiler_test.CompilerTest-class.html#_MustExecutableExitSuccessfully qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.compiler_test.CompilerTest._RunExecutable qm.test.classes.compiler_test.CompilerTest-class.html#_RunExecutable qm.test.classes.compiler_test.CompilerTest._GetLibraryDirectories qm.test.classes.compiler_test.CompilerTest-class.html#_GetLibraryDirectories qm.test.classes.compiler_test.CompilerTest._CheckOutput qm.test.classes.compiler_test.CompilerTest-class.html#_CheckOutput qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.classes.compiler_test.CompilerBase._RemoveDirectory qm.test.classes.compiler_test.CompilerBase-class.html#_RemoveDirectory qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.classes.compiler_test.CompilerTest._ignored_diagnostic_regexps qm.test.classes.compiler_test.CompilerTest-class.html#_ignored_diagnostic_regexps qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.classes.compiler_test.CompilerTest._GetTarget qm.test.classes.compiler_test.CompilerTest-class.html#_GetTarget qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.classes.compiler_test.CompilerTest._IsDiagnosticExpected qm.test.classes.compiler_test.CompilerTest-class.html#_IsDiagnosticExpected qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.classes.compiler_test.CompilerTest._DiagnosticsToString qm.test.classes.compiler_test.CompilerTest-class.html#_DiagnosticsToString qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.test.classes.compiler_test.CompilerTest._CheckExecutableOutput qm.test.classes.compiler_test.CompilerTest-class.html#_CheckExecutableOutput qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.compiler_test.CompilerTest._GetAnnotationPrefix qm.test.classes.compiler_test.CompilerTest-class.html#_GetAnnotationPrefix qm.test.classes.dejagnu_base.DejaGNUBase qm.test.classes.dejagnu_base.DejaGNUBase-class.html qm.test.classes.dejagnu_base.DejaGNUBase._RecordCommandOutput qm.test.classes.dejagnu_base.DejaGNUBase-class.html#_RecordCommandOutput qm.test.classes.dejagnu_base.DejaGNUBase._RecordCommand qm.test.classes.dejagnu_base.DejaGNUBase-class.html#_RecordCommand qm.test.classes.dejagnu_base.DejaGNUBase._SetUp qm.test.classes.dejagnu_base.DejaGNUBase-class.html#_SetUp qm.test.classes.dejagnu_stream.DejaGNUReader qm.test.classes.dejagnu_stream.DejaGNUReader-class.html qm.test.result_reader.ResultReader.GetAnnotations qm.test.result_reader.ResultReader-class.html#GetAnnotations qm.test.file_result_reader.FileResultReader._is_binary_file qm.test.file_result_reader.FileResultReader-class.html#_is_binary_file qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.file_result_reader.FileResultReader.file qm.test.file_result_reader.FileResultReader-class.html#file qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.dejagnu_stream.DejaGNUReader.__init__ qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.dejagnu_stream.DejaGNUReader.__UpdateResult qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#__UpdateResult qm.test.file_result_reader.FileResultReader.InvalidFile qm.test.file_result_reader.FileResultReader.InvalidFile-class.html qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_reader.FileResultReader.filename qm.test.file_result_reader.FileResultReader-class.html#filename qm.test.classes.dejagnu_stream.DejaGNUReader.arguments qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.dejagnu_stream.DejaGNUReader.__cause_regexp qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#__cause_regexp qm.test.classes.dejagnu_stream.DejaGNUReader.GetResult qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#GetResult qm.test.result_reader.ResultReader.__iter__ qm.test.result_reader.ResultReader-class.html#__iter__ qm.test.classes.dejagnu_stream.DejaGNUReader.__GenerateExpectations qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#__GenerateExpectations qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_reader.FileResultReader._argument_dictionary qm.test.file_result_reader.FileResultReader-class.html#_argument_dictionary qm.test.classes.dejagnu_stream.DejaGNUReader.__NextOutcome qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#__NextOutcome qm.test.classes.dejagnu_stream.DejaGNUReader.__id_regexp qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#__id_regexp qm.test.result_reader.ResultReader.kind qm.test.result_reader.ResultReader-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.dejagnu_stream.DejaGNUReader.__UseCombinedMode qm.test.classes.dejagnu_stream.DejaGNUReader-class.html#__UseCombinedMode qm.test.file_result_reader.FileResultReader._argument_list qm.test.file_result_reader.FileResultReader-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.dejagnu_stream.DejaGNUStream qm.test.classes.dejagnu_stream.DejaGNUStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_stream.FileResultStream.file qm.test.file_result_stream.FileResultStream-class.html#file qm.test.file_result_stream.FileResultStream.filename qm.test.file_result_stream.FileResultStream-class.html#filename qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.dejagnu_stream.DejaGNUStream.__init__ qm.test.classes.dejagnu_stream.DejaGNUStream-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.dejagnu_stream.DejaGNUStream.WriteResult qm.test.classes.dejagnu_stream.DejaGNUStream-class.html#WriteResult qm.test.classes.dejagnu_stream.DejaGNUStream.__outcome_descs qm.test.classes.dejagnu_stream.DejaGNUStream-class.html#__outcome_descs qm.test.file_result_stream.FileResultStream._is_binary_file qm.test.file_result_stream.FileResultStream-class.html#_is_binary_file qm.test.classes.dejagnu_stream.DejaGNUStream.arguments qm.test.classes.dejagnu_stream.DejaGNUStream-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.classes.dejagnu_stream.DejaGNUStream.Summarize qm.test.classes.dejagnu_stream.DejaGNUStream-class.html#Summarize qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_stream.FileResultStream._argument_dictionary qm.test.file_result_stream.FileResultStream-class.html#_argument_dictionary qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.test.classes.dejagnu_stream.DejaGNUStream.__expected_outcomes qm.test.classes.dejagnu_stream.DejaGNUStream-class.html#__expected_outcomes qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.file_result_stream.FileResultStream._argument_list qm.test.file_result_stream.FileResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.dejagnu_stream.DejaGNUStream.__summary_outcomes qm.test.classes.dejagnu_stream.DejaGNUStream-class.html#__summary_outcomes qm.test.result_stream.ResultStream.WriteAnnotation qm.test.result_stream.ResultStream-class.html#WriteAnnotation qm.test.classes.dejagnu_test.DejaGNUTest qm.test.classes.dejagnu_test.DejaGNUTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.dejagnu_test.DejaGNUTest.PASS qm.test.classes.dejagnu_test.DejaGNUTest-class.html#PASS qm.test.classes.dejagnu_test.DejaGNUTest.XPASS qm.test.classes.dejagnu_test.DejaGNUTest-class.html#XPASS qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.dejagnu_test.DejaGNUTest.outcome_map qm.test.classes.dejagnu_test.DejaGNUTest-class.html#outcome_map qm.test.classes.dejagnu_test.DejaGNUTest._GetBuild qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_GetBuild qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.classes.dejagnu_test.DejaGNUTest.UNTESTED qm.test.classes.dejagnu_test.DejaGNUTest-class.html#UNTESTED qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.dejagnu_test.DejaGNUTest._GetSourcePath qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_GetSourcePath qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.classes.dejagnu_test.DejaGNUTest.RESULT_PREFIX qm.test.classes.dejagnu_test.DejaGNUTest-class.html#RESULT_PREFIX qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.dejagnu_test.DejaGNUTest.UNRESOLVED qm.test.classes.dejagnu_test.DejaGNUTest-class.html#UNRESOLVED qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.classes.dejagnu_test.DejaGNUTest.executable_timeout qm.test.classes.dejagnu_test.DejaGNUTest-class.html#executable_timeout qm.test.classes.dejagnu_test.DejaGNUTest._SetUp qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_SetUp qm.test.classes.dejagnu_test.DejaGNUTest._Unresolved qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_Unresolved qm.test.classes.dejagnu_test.DejaGNUTest._ParseTclWords qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_ParseTclWords qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.classes.dejagnu_test.DejaGNUTest.WARNING qm.test.classes.dejagnu_test.DejaGNUTest-class.html#WARNING qm.test.classes.dejagnu_test.DejaGNUTest.arguments qm.test.classes.dejagnu_test.DejaGNUTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable-class.html qm.test.classes.dejagnu_test.DejaGNUTest.dejagnu_outcomes qm.test.classes.dejagnu_test.DejaGNUTest-class.html#dejagnu_outcomes qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.classes.dejagnu_test.DejaGNUTest._IsNative qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_IsNative qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.classes.dejagnu_test.DejaGNUTest._RunTargetExecutable qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_RunTargetExecutable qm.test.classes.dejagnu_test.DejaGNUTest._Error qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_Error qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.classes.dejagnu_test.DejaGNUTest.XFAIL qm.test.classes.dejagnu_test.DejaGNUTest-class.html#XFAIL qm.test.classes.dejagnu_test.DejaGNUTest.ERROR qm.test.classes.dejagnu_test.DejaGNUTest-class.html#ERROR qm.test.classes.dejagnu_test.DejaGNUTest.FAIL qm.test.classes.dejagnu_test.DejaGNUTest-class.html#FAIL qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.classes.dejagnu_test.DejaGNUTest._GetTarget qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_GetTarget qm.test.classes.dejagnu_test.DejaGNUTest._RunBuildExecutable qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_RunBuildExecutable qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.dejagnu_test.DejaGNUTest._GetTargetEnvironment qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_GetTargetEnvironment qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.test.classes.dejagnu_test.DejaGNUTest.UNSUPPORTED qm.test.classes.dejagnu_test.DejaGNUTest-class.html#UNSUPPORTED qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.dejagnu_test.DejaGNUTest.KFAIL qm.test.classes.dejagnu_test.DejaGNUTest-class.html#KFAIL qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.dejagnu_test.DejaGNUTest.KPASS qm.test.classes.dejagnu_test.DejaGNUTest-class.html#KPASS qm.test.classes.dejagnu_test.DejaGNUTest._RecordDejaGNUOutcome qm.test.classes.dejagnu_test.DejaGNUTest-class.html#_RecordDejaGNUOutcome qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable-class.html qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable._StderrPipe qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable-class.html#_StderrPipe qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable-class.html qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable._StderrPipe qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable-class.html#_StderrPipe qm.test.classes.dg_test.DGTest qm.test.classes.dg_test.DGTest-class.html qm.test.classes.dg_test.DGTest._RunTool qm.test.classes.dg_test.DGTest-class.html#_RunTool qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.dg_test.DGTest._ExecuteFinalCommand qm.test.classes.dg_test.DGTest-class.html#_ExecuteFinalCommand qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.dg_test.DGTest.KIND_RUN qm.test.classes.dg_test.DGTest-class.html#KIND_RUN qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.classes.dg_test.DGTest.keep_output qm.test.classes.dg_test.DGTest-class.html#keep_output qm.test.classes.dg_test.DGTest.KIND_LINK qm.test.classes.dg_test.DGTest-class.html#KIND_LINK qm.test.classes.dg_test.DGTest.__dg_command_regexp qm.test.classes.dg_test.DGTest-class.html#__dg_command_regexp qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.classes.dg_test.DGTest.__ExpectDiagnostic qm.test.classes.dg_test.DGTest-class.html#__ExpectDiagnostic qm.test.classes.dg_test.DGTest._DGfinal qm.test.classes.dg_test.DGTest-class.html#_DGfinal qm.test.classes.dg_test.DGTest._DGdo qm.test.classes.dg_test.DGTest-class.html#_DGdo qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.dg_test.DGTest.KIND_COMPILE qm.test.classes.dg_test.DGTest-class.html#KIND_COMPILE qm.test.classes.dg_test.DGTest._PruneOutput qm.test.classes.dg_test.DGTest-class.html#_PruneOutput qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.test.classes.dg_test.DGTest._DGerror qm.test.classes.dg_test.DGTest-class.html#_DGerror qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.dg_test.DGTest._DGbogus qm.test.classes.dg_test.DGTest-class.html#_DGbogus qm.test.classes.dg_test.DGTest.__DIAG_ERROR qm.test.classes.dg_test.DGTest-class.html#__DIAG_ERROR qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.classes.dg_test.DGTest.__test_kinds qm.test.classes.dg_test.DGTest-class.html#__test_kinds qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.dg_test.DGTest._DGoptions qm.test.classes.dg_test.DGTest-class.html#_DGoptions qm.test.classes.dg_test.DGTest._RunDGExecutePortion qm.test.classes.dg_test.DGTest-class.html#_RunDGExecutePortion qm.test.classes.dg_test.DGTest.__DIAG_BOGUS qm.test.classes.dg_test.DGTest-class.html#__DIAG_BOGUS qm.test.classes.dg_test.DGTest._default_kind qm.test.classes.dg_test.DGTest-class.html#_default_kind qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable-class.html qm.test.classes.dg_test.DGTest.__DIAG_WARNING qm.test.classes.dg_test.DGTest-class.html#__DIAG_WARNING qm.test.classes.dg_test.DGTest.KIND_PREPROCESS qm.test.classes.dg_test.DGTest-class.html#KIND_PREPROCESS qm.test.classes.dg_test.DGTest._ParseTargetSelector qm.test.classes.dg_test.DGTest-class.html#_ParseTargetSelector qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.classes.dg_test.DGTest._RunDGToolPortion qm.test.classes.dg_test.DGTest-class.html#_RunDGToolPortion qm.test.classes.dg_test.DGTest.DGException qm.test.classes.dg_test.DGTest.DGException-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.classes.dg_test.DGTest.__diagnostic_descriptions qm.test.classes.dg_test.DGTest-class.html#__diagnostic_descriptions qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.classes.dg_test.DGTest._DGwarning qm.test.classes.dg_test.DGTest-class.html#_DGwarning qm.test.classes.dg_test.DGTest._RunDGTest qm.test.classes.dg_test.DGTest-class.html#_RunDGTest qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.test.classes.dg_test.DGTest.KIND_ASSEMBLE qm.test.classes.dg_test.DGTest-class.html#KIND_ASSEMBLE qm.test.classes.dg_test.DGTest._DGexcess_errors qm.test.classes.dg_test.DGTest-class.html#_DGexcess_errors qm.test.classes.dg_test.DGTest.DGException qm.test.classes.dg_test.DGTest.DGException-class.html qm.test.classes.dir_run_database.DirRunDatabase qm.test.classes.dir_run_database.DirRunDatabase-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.dir_run_database.DirRunDatabase.__init__ qm.test.classes.dir_run_database.DirRunDatabase-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.dir_run_database.DirRunDatabase.GetAllRuns qm.test.classes.dir_run_database.DirRunDatabase-class.html#GetAllRuns qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.kind qm.extension.Extension-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.explicit_suite.ExplicitSuite qm.test.classes.explicit_suite.ExplicitSuite-class.html qm.test.suite.Suite.GetAllTestAndSuiteIds qm.test.suite.Suite-class.html#GetAllTestAndSuiteIds qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.explicit_suite.ExplicitSuite.is_implicit qm.test.classes.explicit_suite.ExplicitSuite-class.html#is_implicit qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.suite.Suite.__init__ qm.test.suite.Suite-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.explicit_suite.ExplicitSuite.IsImplicit qm.test.classes.explicit_suite.ExplicitSuite-class.html#IsImplicit qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.explicit_suite.ExplicitSuite.arguments qm.test.classes.explicit_suite.ExplicitSuite-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.explicit_suite.ExplicitSuite.GetTestIds qm.test.classes.explicit_suite.ExplicitSuite-class.html#GetTestIds qm.test.suite.Suite.GetDatabase qm.test.suite.Suite-class.html#GetDatabase qm.test.suite.Suite.GetId qm.test.suite.Suite-class.html#GetId qm.test.classes.explicit_suite.ExplicitSuite.GetSuiteIds qm.test.classes.explicit_suite.ExplicitSuite-class.html#GetSuiteIds qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.classes.explicit_suite.ExplicitSuite._argument_dictionary qm.test.classes.explicit_suite.ExplicitSuite-class.html#_argument_dictionary qm.test.suite.Suite.kind qm.test.suite.Suite-class.html#kind qm.test.suite.Suite.EXTRA_DATABASE qm.test.suite.Suite-class.html#EXTRA_DATABASE qm.test.suite.Suite.EXTRA_ID qm.test.suite.Suite-class.html#EXTRA_ID qm.test.classes.explicit_suite.ExplicitSuite.suite_ids qm.test.classes.explicit_suite.ExplicitSuite-class.html#suite_ids qm.test.classes.explicit_suite.ExplicitSuite.test_ids qm.test.classes.explicit_suite.ExplicitSuite-class.html#test_ids qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.explicit_suite.ExplicitSuite._argument_list qm.test.classes.explicit_suite.ExplicitSuite-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.file.FileContentsTest qm.test.classes.file.FileContentsTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.file.FileContentsTest.Run qm.test.classes.file.FileContentsTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.file.FileContentsTest.arguments qm.test.classes.file.FileContentsTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.classes.file.FileContentsTest.__PerformSubstitutions qm.test.classes.file.FileContentsTest-class.html#__PerformSubstitutions qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.file.SubstitutionField qm.test.classes.file.SubstitutionField-class.html qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.Field.FormatValueAsText qm.fields.Field-class.html#FormatValueAsText qm.test.classes.file.SubstitutionField.GetHelp qm.test.classes.file.SubstitutionField-class.html#GetHelp qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.test.classes.file.SubstitutionField.__init__ qm.test.classes.file.SubstitutionField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.Field.ParseTextValue qm.fields.Field-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.test.classes.file_label.FileLabel qm.test.classes.file_label.FileLabel-class.html qm.label.Label.SplitLeft qm.label.Label-class.html#SplitLeft qm.test.classes.file_label.FileLabel.Join qm.test.classes.file_label.FileLabel-class.html#Join qm.label.Label.IsValid qm.label.Label-class.html#IsValid qm.test.classes.file_label.FileLabel.Basename qm.test.classes.file_label.FileLabel-class.html#Basename qm.test.classes.file_label.FileLabel.Split qm.test.classes.file_label.FileLabel-class.html#Split qm.test.classes.file_label.FileLabel._sep qm.test.classes.file_label.FileLabel-class.html#_sep qm.test.classes.file_label.FileLabel.Dirname qm.test.classes.file_label.FileLabel-class.html#Dirname qm.label.Label.__str__ qm.label.Label-class.html#__str__ qm.label.Label.__init__ qm.label.Label-class.html#__init__ qm.test.classes.local_host.LocalHost qm.test.classes.local_host.LocalHost-class.html qm.host.Host.Executable qm.host.Host.Executable-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.local_host.LocalHost.DownloadFile qm.test.classes.local_host.LocalHost-class.html#DownloadFile qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.local_host.LocalHost.DeleteFile qm.test.classes.local_host.LocalHost-class.html#DeleteFile qm.test.classes.local_host.LocalHost._SameFile qm.test.classes.local_host.LocalHost-class.html#_SameFile qm.test.classes.local_host.LocalHost.UploadFile qm.test.classes.local_host.LocalHost-class.html#UploadFile qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.local_host.LocalHost.UploadAndRun qm.test.classes.local_host.LocalHost-class.html#UploadAndRun qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.mount_database.MountDatabase qm.test.classes.mount_database.MountDatabase-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.mount_database.MountDatabase.MountedSuite qm.test.classes.mount_database.MountDatabase.MountedSuite-class.html qm.test.database.Database.modifiable qm.test.database.Database-class.html#modifiable qm.test.database.Database.GetResourceClassNames qm.test.database.Database-class.html#GetResourceClassNames qm.test.classes.mount_database.MountDatabase.GetTest qm.test.classes.mount_database.MountDatabase-class.html#GetTest qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.mount_database.MountDatabase.GetSuite qm.test.classes.mount_database.MountDatabase-class.html#GetSuite qm.test.database.Database.HasTest qm.test.database.Database-class.html#HasTest qm.test.database.Database.RemoveExtension qm.test.database.Database-class.html#RemoveExtension qm.test.database.Database.SUITE qm.test.database.Database-class.html#SUITE qm.test.database.Database.GetExtensions qm.test.database.Database-class.html#GetExtensions qm.test.database.Database.IsValidLabel qm.test.database.Database-class.html#IsValidLabel qm.test.classes.mount_database.MountDatabase._AdjustResources qm.test.classes.mount_database.MountDatabase-class.html#_AdjustResources qm.test.classes.mount_database.MountDatabase.__init__ qm.test.classes.mount_database.MountDatabase-class.html#__init__ qm.test.database.Database.GetResourceIds qm.test.database.Database-class.html#GetResourceIds qm.test.database.Database.RESOURCE qm.test.database.Database-class.html#RESOURCE qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.database.Database.JoinLabels qm.test.database.Database-class.html#JoinLabels qm.test.classes.mount_database.MountDatabase._GetContainedItem qm.test.classes.mount_database.MountDatabase-class.html#_GetContainedItem qm.test.classes.mount_database.MountDatabase.GetResource qm.test.classes.mount_database.MountDatabase-class.html#GetResource qm.test.database.Database.label_class qm.test.database.Database-class.html#label_class qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.database.Database.ExpandIds qm.test.database.Database-class.html#ExpandIds qm.test.database.Database.SplitLabel qm.test.database.Database-class.html#SplitLabel qm.test.classes.mount_database.MountDatabase.GetSubdirectories qm.test.classes.mount_database.MountDatabase-class.html#GetSubdirectories qm.test.database.Database.arguments qm.test.database.Database-class.html#arguments qm.test.database.Database.GetConfigurationDirectory qm.test.database.Database-class.html#GetConfigurationDirectory qm.test.classes.mount_database.MountDatabase._SelectDatabase qm.test.classes.mount_database.MountDatabase-class.html#_SelectDatabase qm.test.database.Database.GetTestIds qm.test.database.Database-class.html#GetTestIds qm.test.classes.mount_database.MountDatabase.GetClassPaths qm.test.classes.mount_database.MountDatabase-class.html#GetClassPaths qm.test.database.Database.HasResource qm.test.database.Database-class.html#HasResource qm.test.database.Database.GetTestClassNames qm.test.database.Database-class.html#GetTestClassNames qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.database.Database.WriteExtension qm.test.database.Database-class.html#WriteExtension qm.test.database.Database.SplitLabelLeft qm.test.database.Database-class.html#SplitLabelLeft qm.test.database.Database.GetAttachmentStore qm.test.database.Database-class.html#GetAttachmentStore qm.test.database.Database.TEST qm.test.database.Database-class.html#TEST qm.test.database.Database.IsModifiable qm.test.database.Database-class.html#IsModifiable qm.test.classes.mount_database.MountDatabase.GetIds qm.test.classes.mount_database.MountDatabase-class.html#GetIds qm.test.database.Database.GetPath qm.test.database.Database-class.html#GetPath qm.test.database.Database.GetExtension qm.test.database.Database-class.html#GetExtension qm.test.database.Database.GetLabelComponents qm.test.database.Database-class.html#GetLabelComponents qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.database.Database.HasSuite qm.test.database.Database-class.html#HasSuite qm.test.classes.mount_database.MountDatabase._argument_dictionary qm.test.classes.mount_database.MountDatabase-class.html#_argument_dictionary qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.database.Database.kind qm.test.database.Database-class.html#kind qm.test.database.Database.ITEM_KINDS qm.test.database.Database-class.html#ITEM_KINDS qm.test.database.Database._item_exceptions qm.test.database.Database-class.html#_item_exceptions qm.test.database.Database._is_generic_database qm.test.database.Database-class.html#_is_generic_database qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.database.Database.GetItem qm.test.database.Database-class.html#GetItem qm.test.classes.mount_database.MountDatabase._argument_list qm.test.classes.mount_database.MountDatabase-class.html#_argument_list qm.test.classes.mount_database.MountDatabase.mounts qm.test.classes.mount_database.MountDatabase-class.html#mounts qm.test.database.Database.GetSuiteIds qm.test.database.Database-class.html#GetSuiteIds qm.test.classes.mount_database.MountDatabase.MountedSuite qm.test.classes.mount_database.MountDatabase.MountedSuite-class.html qm.test.suite.Suite.GetAllTestAndSuiteIds qm.test.suite.Suite-class.html#GetAllTestAndSuiteIds qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.mount_database.MountDatabase.MountedSuite.__init__ qm.test.classes.mount_database.MountDatabase.MountedSuite-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.mount_database.MountDatabase.MountedSuite.IsImplicit qm.test.classes.mount_database.MountDatabase.MountedSuite-class.html#IsImplicit qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.suite.Suite.arguments qm.test.suite.Suite-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.mount_database.MountDatabase.MountedSuite.GetTestIds qm.test.classes.mount_database.MountDatabase.MountedSuite-class.html#GetTestIds qm.test.suite.Suite.GetDatabase qm.test.suite.Suite-class.html#GetDatabase qm.test.suite.Suite.GetId qm.test.suite.Suite-class.html#GetId qm.test.classes.mount_database.MountDatabase.MountedSuite.GetSuiteIds qm.test.classes.mount_database.MountDatabase.MountedSuite-class.html#GetSuiteIds qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.suite.Suite.kind qm.test.suite.Suite-class.html#kind qm.test.suite.Suite.EXTRA_DATABASE qm.test.suite.Suite-class.html#EXTRA_DATABASE qm.test.suite.Suite.EXTRA_ID qm.test.suite.Suite-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.pickle_result_stream.PickleResultReader qm.test.classes.pickle_result_stream.PickleResultReader-class.html qm.test.classes.pickle_result_stream.PickleResultReader.GetAnnotations qm.test.classes.pickle_result_stream.PickleResultReader-class.html#GetAnnotations qm.test.file_result_reader.FileResultReader._is_binary_file qm.test.file_result_reader.FileResultReader-class.html#_is_binary_file qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.file_result_reader.FileResultReader.file qm.test.file_result_reader.FileResultReader-class.html#file qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.pickle_result_stream.PickleResultReader.__init__ qm.test.classes.pickle_result_stream.PickleResultReader-class.html#__init__ qm.test.classes.pickle_result_stream.PickleResultReader._ResetUnpickler qm.test.classes.pickle_result_stream.PickleResultReader-class.html#_ResetUnpickler qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.file_result_reader.FileResultReader.InvalidFile qm.test.file_result_reader.FileResultReader.InvalidFile-class.html qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_reader.FileResultReader.filename qm.test.file_result_reader.FileResultReader-class.html#filename qm.test.classes.pickle_result_stream.PickleResultReader._ReadAddress qm.test.classes.pickle_result_stream.PickleResultReader-class.html#_ReadAddress qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.file_result_reader.FileResultReader.arguments qm.test.file_result_reader.FileResultReader-class.html#arguments qm.test.classes.pickle_result_stream.PickleResultReader._ReadMetadata qm.test.classes.pickle_result_stream.PickleResultReader-class.html#_ReadMetadata qm.test.classes.pickle_result_stream.PickleResultReader.GetResult qm.test.classes.pickle_result_stream.PickleResultReader-class.html#GetResult qm.test.result_reader.ResultReader.__iter__ qm.test.result_reader.ResultReader-class.html#__iter__ qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_reader.FileResultReader._argument_dictionary qm.test.file_result_reader.FileResultReader-class.html#_argument_dictionary qm.test.result_reader.ResultReader.kind qm.test.result_reader.ResultReader-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.file_result_reader.FileResultReader._argument_list qm.test.file_result_reader.FileResultReader-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.pickle_result_stream.PickleResultStream qm.test.classes.pickle_result_stream.PickleResultStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.pickle_result_stream.PickleResultStream._is_binary_file qm.test.classes.pickle_result_stream.PickleResultStream-class.html#_is_binary_file qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.pickle_result_stream.PickleResultStream._WriteAnnotationPtr qm.test.classes.pickle_result_stream.PickleResultStream-class.html#_WriteAnnotationPtr qm.test.file_result_stream.FileResultStream.file qm.test.file_result_stream.FileResultStream-class.html#file qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.pickle_result_stream.PickleResultStream.__init__ qm.test.classes.pickle_result_stream.PickleResultStream-class.html#__init__ qm.test.classes.pickle_result_stream.PickleResultStream._format_version qm.test.classes.pickle_result_stream.PickleResultStream-class.html#_format_version qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.pickle_result_stream.PickleResultStream.WriteResult qm.test.classes.pickle_result_stream.PickleResultStream-class.html#WriteResult qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_stream.FileResultStream.filename qm.test.file_result_stream.FileResultStream-class.html#filename qm.test.classes.pickle_result_stream.PickleResultStream._max_pinned_results qm.test.classes.pickle_result_stream.PickleResultStream-class.html#_max_pinned_results qm.test.classes.pickle_result_stream.PickleResultStream.arguments qm.test.classes.pickle_result_stream.PickleResultStream-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.result_stream.ResultStream.Summarize qm.test.result_stream.ResultStream-class.html#Summarize qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.test.classes.pickle_result_stream.PickleResultStream.protocol_version qm.test.classes.pickle_result_stream.PickleResultStream-class.html#protocol_version qm.test.classes.pickle_result_stream.PickleResultStream._ResetPickler qm.test.classes.pickle_result_stream.PickleResultStream-class.html#_ResetPickler qm.test.classes.pickle_result_stream.PickleResultStream._argument_dictionary qm.test.classes.pickle_result_stream.PickleResultStream-class.html#_argument_dictionary qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.pickle_result_stream.PickleResultStream._argument_list qm.test.classes.pickle_result_stream.PickleResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.pickle_result_stream.PickleResultStream.WriteAnnotation qm.test.classes.pickle_result_stream.PickleResultStream-class.html#WriteAnnotation qm.test.classes.previous_testrun.PreviousTestRun qm.test.classes.previous_testrun.PreviousTestRun-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.previous_testrun.PreviousTestRun.file_name qm.test.classes.previous_testrun.PreviousTestRun-class.html#file_name qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.previous_testrun.PreviousTestRun.results_file qm.test.classes.previous_testrun.PreviousTestRun-class.html#results_file qm.test.classes.previous_testrun.PreviousTestRun.Lookup qm.test.classes.previous_testrun.PreviousTestRun-class.html#Lookup qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.previous_testrun.PreviousTestRun.__init__ qm.test.classes.previous_testrun.PreviousTestRun-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.process_target.ProcessTarget qm.test.classes.process_target.ProcessTarget-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.process_target.ProcessTarget.RunTest qm.test.classes.process_target.ProcessTarget-class.html#RunTest qm.test.classes.process_target.ProcessTarget.Start qm.test.classes.process_target.ProcessTarget-class.html#Start qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.process_target.ProcessTarget.__init__ qm.test.classes.process_target.ProcessTarget-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.process_target.ProcessTarget.Stop qm.test.classes.process_target.ProcessTarget-class.html#Stop qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.process_target.ProcessTarget.arguments qm.test.classes.process_target.ProcessTarget-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.process_target.ProcessTarget.QMTestExecutable qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.html qm.test.classes.process_target.ProcessTarget.__ReadResults qm.test.classes.process_target.ProcessTarget-class.html#__ReadResults qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.process_target.ProcessTarget._GetInterpreter qm.test.classes.process_target.ProcessTarget-class.html#_GetInterpreter qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.test.classes.process_target.ProcessTarget.IsIdle qm.test.classes.process_target.ProcessTarget-class.html#IsIdle qm.test.classes.process_target.ProcessTarget.QMTestExecutable qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.html qm.test.classes.process_target.ProcessTarget.QMTestExecutable._InitializeParent qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.html#_InitializeParent qm.test.classes.process_target.ProcessTarget.QMTestExecutable._InitializeChild qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.html#_InitializeChild qm.test.classes.process_target.ProcessTarget.QMTestExecutable qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.html qm.test.classes.process_target.ProcessTarget.QMTestExecutable._InitializeParent qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.html#_InitializeParent qm.test.classes.process_target.ProcessTarget.QMTestExecutable._InitializeChild qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.html#_InitializeChild qm.test.classes.python.BaseExceptionTest qm.test.classes.python.BaseExceptionTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.python.BaseExceptionTest.CheckArgument qm.test.classes.python.BaseExceptionTest-class.html#CheckArgument qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.python.BaseExceptionTest.Run qm.test.classes.python.BaseExceptionTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.python.BaseExceptionTest.arguments qm.test.classes.python.BaseExceptionTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.classes.python.BaseExceptionTest.MakeResult qm.test.classes.python.BaseExceptionTest-class.html#MakeResult qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.python.ExceptionTest qm.test.classes.python.ExceptionTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.python.ExceptionTest.CheckArgument qm.test.classes.python.ExceptionTest-class.html#CheckArgument qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.python.BaseExceptionTest.Run qm.test.classes.python.BaseExceptionTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.python.ExceptionTest.arguments qm.test.classes.python.ExceptionTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.classes.python.ExceptionTest.MakeResult qm.test.classes.python.ExceptionTest-class.html#MakeResult qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.python.ExecTest qm.test.classes.python.ExecTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.python.ExecTest.Run qm.test.classes.python.ExecTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.python.ExecTest.arguments qm.test.classes.python.ExecTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.python.StringExceptionTest qm.test.classes.python.StringExceptionTest-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.python.BaseExceptionTest.CheckArgument qm.test.classes.python.BaseExceptionTest-class.html#CheckArgument qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.classes.python.BaseExceptionTest.Run qm.test.classes.python.BaseExceptionTest-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.python.StringExceptionTest.arguments qm.test.classes.python.StringExceptionTest-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.classes.python.StringExceptionTest.MakeResult qm.test.classes.python.StringExceptionTest-class.html#MakeResult qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.python_label.PythonLabel qm.test.classes.python_label.PythonLabel-class.html qm.label.Label.SplitLeft qm.label.Label-class.html#SplitLeft qm.label.Label.Join qm.label.Label-class.html#Join qm.test.classes.python_label.PythonLabel.__valid_label_regexp qm.test.classes.python_label.PythonLabel-class.html#__valid_label_regexp qm.test.classes.python_label.PythonLabel.IsValid qm.test.classes.python_label.PythonLabel-class.html#IsValid qm.label.Label.Basename qm.label.Label-class.html#Basename qm.label.Label.Split qm.label.Label-class.html#Split qm.test.classes.python_label.PythonLabel._sep qm.test.classes.python_label.PythonLabel-class.html#_sep qm.label.Label.Dirname qm.label.Label-class.html#Dirname qm.label.Label.__str__ qm.label.Label-class.html#__str__ qm.label.Label.__init__ qm.label.Label-class.html#__init__ qm.test.classes.rsh_target.RSHTarget qm.test.classes.rsh_target.RSHTarget-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.rsh_target.RSHTarget.remote_shell qm.test.classes.rsh_target.RSHTarget-class.html#remote_shell qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.rsh_target.RSHTarget.__init__ qm.test.classes.rsh_target.RSHTarget-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.rsh_target.RSHTarget.arguments qm.test.classes.rsh_target.RSHTarget-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.process_target.ProcessTarget.QMTestExecutable qm.test.classes.process_target.ProcessTarget.QMTestExecutable-class.html qm.test.classes.rsh_target.RSHTarget.host qm.test.classes.rsh_target.RSHTarget-class.html#host qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.rsh_target.RSHTarget._GetInterpreter qm.test.classes.rsh_target.RSHTarget-class.html#_GetInterpreter qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.test.classes.serial_target.SerialTarget qm.test.classes.serial_target.SerialTarget-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.serial_target.SerialTarget.__init__ qm.test.classes.serial_target.SerialTarget-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.serial_target.SerialTarget._GetTemporaryDirectory qm.test.classes.serial_target.SerialTarget-class.html#_GetTemporaryDirectory qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.test.classes.serial_target.SerialTarget.IsIdle qm.test.classes.serial_target.SerialTarget-class.html#IsIdle qm.test.classes.simulator.Simulator qm.test.classes.simulator.Simulator-class.html qm.host.Host.Executable qm.host.Host.Executable-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.simulator.Simulator.simulator qm.test.classes.simulator.Simulator-class.html#simulator qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.simulator.Simulator.Run qm.test.classes.simulator.Simulator-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.simulator.Simulator.simulator_args qm.test.classes.simulator.Simulator-class.html#simulator_args qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.sql_result_stream.SQLResultReader qm.test.classes.sql_result_stream.SQLResultReader-class.html qm.test.classes.sql_result_stream.SQLResultReader.GetAnnotations qm.test.classes.sql_result_stream.SQLResultReader-class.html#GetAnnotations qm.test.classes.sql_result_stream.SQLResultReader._SetupResultCursors qm.test.classes.sql_result_stream.SQLResultReader-class.html#_SetupResultCursors qm.test.classes.sql_result_stream.SQLResultReader.run_id qm.test.classes.sql_result_stream.SQLResultReader-class.html#run_id qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.sql_result_stream.SQLResultReader.__init__ qm.test.classes.sql_result_stream.SQLResultReader-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.sql_result_stream.SQLResultReader.arguments qm.test.classes.sql_result_stream.SQLResultReader-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.sql_result_stream._SQLConnected.db_module qm.test.classes.sql_result_stream._SQLConnected-class.html#db_module qm.test.classes.sql_result_stream.SQLResultReader.GetResult qm.test.classes.sql_result_stream.SQLResultReader-class.html#GetResult qm.test.result_reader.ResultReader.__iter__ qm.test.result_reader.ResultReader-class.html#__iter__ qm.test.classes.sql_result_stream._SQLConnected.db_name qm.test.classes.sql_result_stream._SQLConnected-class.html#db_name qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.classes.sql_result_stream.SQLResultReader._argument_dictionary qm.test.classes.sql_result_stream.SQLResultReader-class.html#_argument_dictionary qm.test.classes.sql_result_stream.SQLResultReader._LoadAnnotations qm.test.classes.sql_result_stream.SQLResultReader-class.html#_LoadAnnotations qm.test.result_reader.ResultReader.kind qm.test.result_reader.ResultReader-class.html#kind qm.test.classes.sql_result_stream._SQLConnected.connection qm.test.classes.sql_result_stream._SQLConnected-class.html#connection qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.sql_result_stream.SQLResultReader._argument_list qm.test.classes.sql_result_stream.SQLResultReader-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.sql_result_stream.SQLResultStream qm.test.classes.sql_result_stream.SQLResultStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.sql_result_stream.SQLResultStream.__init__ qm.test.classes.sql_result_stream.SQLResultStream-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.sql_result_stream.SQLResultStream.WriteResult qm.test.classes.sql_result_stream.SQLResultStream-class.html#WriteResult qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.sql_result_stream._SQLConnected.arguments qm.test.classes.sql_result_stream._SQLConnected-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.classes.sql_result_stream.SQLResultStream.Summarize qm.test.classes.sql_result_stream.SQLResultStream-class.html#Summarize qm.test.classes.sql_result_stream._SQLConnected.db_module qm.test.classes.sql_result_stream._SQLConnected-class.html#db_module qm.test.classes.sql_result_stream._SQLConnected.db_name qm.test.classes.sql_result_stream._SQLConnected-class.html#db_name qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.classes.sql_result_stream.SQLResultStream._argument_dictionary qm.test.classes.sql_result_stream.SQLResultStream-class.html#_argument_dictionary qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.test.classes.sql_result_stream._SQLConnected.connection qm.test.classes.sql_result_stream._SQLConnected-class.html#connection qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.sql_result_stream.SQLResultStream._argument_list qm.test.classes.sql_result_stream.SQLResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.sql_result_stream.SQLResultStream.WriteAnnotation qm.test.classes.sql_result_stream.SQLResultStream-class.html#WriteAnnotation qm.test.classes.sql_result_stream._Buffer qm.test.classes.sql_result_stream._Buffer-class.html qm.test.classes.sql_result_stream._Buffer.__iter__ qm.test.classes.sql_result_stream._Buffer-class.html#__iter__ qm.test.classes.sql_result_stream._Buffer.rewind qm.test.classes.sql_result_stream._Buffer-class.html#rewind qm.test.classes.sql_result_stream._Buffer.__init__ qm.test.classes.sql_result_stream._Buffer-class.html#__init__ qm.test.classes.sql_result_stream._Buffer.next qm.test.classes.sql_result_stream._Buffer-class.html#next qm.test.classes.sql_result_stream._SQLConnected qm.test.classes.sql_result_stream._SQLConnected-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.sql_result_stream._SQLConnected.__init__ qm.test.classes.sql_result_stream._SQLConnected-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.sql_result_stream._SQLConnected.arguments qm.test.classes.sql_result_stream._SQLConnected-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.sql_result_stream._SQLConnected.db_module qm.test.classes.sql_result_stream._SQLConnected-class.html#db_module qm.test.classes.sql_result_stream._SQLConnected.db_name qm.test.classes.sql_result_stream._SQLConnected-class.html#db_name qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.classes.sql_result_stream._SQLConnected._argument_dictionary qm.test.classes.sql_result_stream._SQLConnected-class.html#_argument_dictionary qm.extension.Extension.kind qm.extension.Extension-class.html#kind qm.test.classes.sql_result_stream._SQLConnected.connection qm.test.classes.sql_result_stream._SQLConnected-class.html#connection qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.sql_result_stream._SQLConnected._argument_list qm.test.classes.sql_result_stream._SQLConnected-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.ssh_host.RSHHost qm.test.classes.ssh_host.RSHHost-class.html qm.host.Host.Executable qm.host.Host.Executable-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.ssh_host.SSHHost._FormSCPCommandLine qm.test.classes.ssh_host.SSHHost-class.html#_FormSCPCommandLine qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.ssh_host.SSHHost._FormSSHCommandLine qm.test.classes.ssh_host.SSHHost-class.html#_FormSSHCommandLine qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.ssh_host.SSHHost.scp_args qm.test.classes.ssh_host.SSHHost-class.html#scp_args qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.ssh_host.RSHHost.Run qm.test.classes.ssh_host.RSHHost-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.ssh_host.SSHHost.DownloadFile qm.test.classes.ssh_host.SSHHost-class.html#DownloadFile qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.ssh_host.SSHHost.user_name qm.test.classes.ssh_host.SSHHost-class.html#user_name qm.test.classes.ssh_host.SSHHost.DeleteFile qm.test.classes.ssh_host.SSHHost-class.html#DeleteFile qm.test.classes.ssh_host.SSHHost.UploadFile qm.test.classes.ssh_host.SSHHost-class.html#UploadFile qm.test.classes.ssh_host.SSHHost.nfs_dir qm.test.classes.ssh_host.SSHHost-class.html#nfs_dir qm.test.classes.ssh_host.SSHHost.default_dir qm.test.classes.ssh_host.SSHHost-class.html#default_dir qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.classes.ssh_host.RSHHost.scp_program qm.test.classes.ssh_host.RSHHost-class.html#scp_program qm.test.classes.ssh_host.RSHHost.ssh_program qm.test.classes.ssh_host.RSHHost-class.html#ssh_program qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.ssh_host.SSHHost.host_name qm.test.classes.ssh_host.SSHHost-class.html#host_name qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.ssh_host.SSHHost.ssh_args qm.test.classes.ssh_host.SSHHost-class.html#ssh_args qm.test.classes.ssh_host.SSHHost qm.test.classes.ssh_host.SSHHost-class.html qm.host.Host.Executable qm.host.Host.Executable-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.ssh_host.SSHHost._FormSCPCommandLine qm.test.classes.ssh_host.SSHHost-class.html#_FormSCPCommandLine qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.ssh_host.SSHHost._FormSSHCommandLine qm.test.classes.ssh_host.SSHHost-class.html#_FormSSHCommandLine qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.ssh_host.SSHHost.scp_args qm.test.classes.ssh_host.SSHHost-class.html#scp_args qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.ssh_host.SSHHost.default_dir qm.test.classes.ssh_host.SSHHost-class.html#default_dir qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.ssh_host.SSHHost.DownloadFile qm.test.classes.ssh_host.SSHHost-class.html#DownloadFile qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.ssh_host.SSHHost.user_name qm.test.classes.ssh_host.SSHHost-class.html#user_name qm.test.classes.ssh_host.SSHHost.DeleteFile qm.test.classes.ssh_host.SSHHost-class.html#DeleteFile qm.test.classes.ssh_host.SSHHost.UploadFile qm.test.classes.ssh_host.SSHHost-class.html#UploadFile qm.test.classes.ssh_host.SSHHost.nfs_dir qm.test.classes.ssh_host.SSHHost-class.html#nfs_dir qm.test.classes.ssh_host.SSHHost.Run qm.test.classes.ssh_host.SSHHost-class.html#Run qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.classes.ssh_host.SSHHost.scp_program qm.test.classes.ssh_host.SSHHost-class.html#scp_program qm.test.classes.ssh_host.SSHHost.ssh_program qm.test.classes.ssh_host.SSHHost-class.html#ssh_program qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.ssh_host.SSHHost.host_name qm.test.classes.ssh_host.SSHHost-class.html#host_name qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.ssh_host.SSHHost.ssh_args qm.test.classes.ssh_host.SSHHost-class.html#ssh_args qm.test.classes.temporary.TempDirectoryResource qm.test.classes.temporary.TempDirectoryResource-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.classes.temporary.TempDirectoryResource.dir_path_property qm.test.classes.temporary.TempDirectoryResource-class.html#dir_path_property qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.temporary.TempDirectoryResource.CleanUp qm.test.classes.temporary.TempDirectoryResource-class.html#CleanUp qm.test.classes.temporary.TempDirectoryResource.arguments qm.test.classes.temporary.TempDirectoryResource-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.classes.temporary.TempDirectoryResource.delete_recursively qm.test.classes.temporary.TempDirectoryResource-class.html#delete_recursively qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.classes.temporary.TempDirectoryResource._argument_dictionary qm.test.classes.temporary.TempDirectoryResource-class.html#_argument_dictionary qm.test.resource.Resource.kind qm.test.resource.Resource-class.html#kind qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.classes.temporary.TempDirectoryResource.SetUp qm.test.classes.temporary.TempDirectoryResource-class.html#SetUp qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.temporary.TempDirectoryResource._argument_list qm.test.classes.temporary.TempDirectoryResource-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.test.classes.tet_stream.TETStream qm.test.classes.tet_stream.TETStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_stream.FileResultStream.file qm.test.file_result_stream.FileResultStream-class.html#file qm.test.classes.tet_stream.TETStream.UNTESTED qm.test.classes.tet_stream.TETStream-class.html#UNTESTED qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.tet_stream.TETStream.__init__ qm.test.classes.tet_stream.TETStream-class.html#__init__ qm.test.classes.tet_stream.TETStream._WriteResourceResult qm.test.classes.tet_stream.TETStream-class.html#_WriteResourceResult qm.test.file_result_stream.FileResultStream._argument_dictionary qm.test.file_result_stream.FileResultStream-class.html#_argument_dictionary qm.test.classes.tet_stream.TETStream.UNRESOLVED qm.test.classes.tet_stream.TETStream-class.html#UNRESOLVED qm.test.classes.tet_stream.TETStream._WriteResultAnnotations qm.test.classes.tet_stream.TETStream-class.html#_WriteResultAnnotations qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.tet_stream.TETStream._WriteLine qm.test.classes.tet_stream.TETStream-class.html#_WriteLine qm.test.classes.tet_stream.TETStream.WriteResult qm.test.classes.tet_stream.TETStream-class.html#WriteResult qm.test.classes.tet_stream.TETStream._TETFormatTime qm.test.classes.tet_stream.TETStream-class.html#_TETFormatTime qm.test.file_result_stream.FileResultStream.filename qm.test.file_result_stream.FileResultStream-class.html#filename qm.test.classes.tet_stream.TETStream.WARNING qm.test.classes.tet_stream.TETStream-class.html#WARNING qm.test.file_result_stream.FileResultStream.arguments qm.test.file_result_stream.FileResultStream-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.tet_stream.TETStream._ExtractTime qm.test.classes.tet_stream.TETStream-class.html#_ExtractTime qm.test.classes.tet_stream.TETStream.Summarize qm.test.classes.tet_stream.TETStream-class.html#Summarize qm.test.classes.tet_stream.TETStream.FIP qm.test.classes.tet_stream.TETStream-class.html#FIP qm.test.classes.tet_stream.TETStream._WriteTCStart qm.test.classes.tet_stream.TETStream-class.html#_WriteTCStart qm.test.classes.tet_stream.TETStream._WriteInitialStuff qm.test.classes.tet_stream.TETStream-class.html#_WriteInitialStuff qm.test.classes.tet_stream.TETStream._WriteDejaGNUResult qm.test.classes.tet_stream.TETStream-class.html#_WriteDejaGNUResult qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.test.classes.tet_stream.TETStream.PASS qm.test.classes.tet_stream.TETStream-class.html#PASS qm.test.classes.tet_stream.TETStream.FAIL qm.test.classes.tet_stream.TETStream-class.html#FAIL qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_stream.FileResultStream._is_binary_file qm.test.file_result_stream.FileResultStream-class.html#_is_binary_file qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.classes.tet_stream.TETStream._WriteTestResult qm.test.classes.tet_stream.TETStream-class.html#_WriteTestResult qm.test.classes.tet_stream.TETStream._IsDejaGNUResult qm.test.classes.tet_stream.TETStream-class.html#_IsDejaGNUResult qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.classes.tet_stream.TETStream.UNSUPPORTED qm.test.classes.tet_stream.TETStream-class.html#UNSUPPORTED qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.tet_stream.TETStream.UNREPORTED qm.test.classes.tet_stream.TETStream-class.html#UNREPORTED qm.test.file_result_stream.FileResultStream._argument_list qm.test.file_result_stream.FileResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.tet_stream.TETStream.UNINITIATED qm.test.classes.tet_stream.TETStream-class.html#UNINITIATED qm.test.classes.tet_stream.TETStream.WriteAnnotation qm.test.classes.tet_stream.TETStream-class.html#WriteAnnotation qm.test.classes.tet_stream.TETStream.NOTINUSE qm.test.classes.tet_stream.TETStream-class.html#NOTINUSE qm.test.classes.text_result_stream.TextResultStream qm.test.classes.text_result_stream.TextResultStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.file_result_stream.FileResultStream.file qm.test.file_result_stream.FileResultStream-class.html#file qm.test.classes.text_result_stream.TextResultStream._SummarizeResults qm.test.classes.text_result_stream.TextResultStream-class.html#_SummarizeResults qm.test.file_result_stream.FileResultStream.filename qm.test.file_result_stream.FileResultStream-class.html#filename qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.text_result_stream.TextResultStream.__init__ qm.test.classes.text_result_stream.TextResultStream-class.html#__init__ qm.test.classes.text_result_stream.TextResultStream._DisplayHeading qm.test.classes.text_result_stream.TextResultStream-class.html#_DisplayHeading qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.text_result_stream.TextResultStream._SummarizeTestStats qm.test.classes.text_result_stream.TextResultStream-class.html#_SummarizeTestStats qm.test.classes.text_result_stream.TextResultStream.WriteResult qm.test.classes.text_result_stream.TextResultStream-class.html#WriteResult qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_stream.FileResultStream._is_binary_file qm.test.file_result_stream.FileResultStream-class.html#_is_binary_file qm.test.classes.text_result_stream.TextResultStream._SummarizeRelativeTestStats qm.test.classes.text_result_stream.TextResultStream-class.html#_SummarizeRelativeTestStats qm.test.classes.text_result_stream.TextResultStream._DisplayStatistics qm.test.classes.text_result_stream.TextResultStream-class.html#_DisplayStatistics qm.test.classes.text_result_stream.TextResultStream.arguments qm.test.classes.text_result_stream.TextResultStream-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.classes.text_result_stream.TextResultStream.Summarize qm.test.classes.text_result_stream.TextResultStream-class.html#Summarize qm.test.classes.text_result_stream.TextResultStream._WriteOutcome qm.test.classes.text_result_stream.TextResultStream-class.html#_WriteOutcome qm.test.classes.text_result_stream.TextResultStream._FormatStatistics qm.test.classes.text_result_stream.TextResultStream-class.html#_FormatStatistics qm.test.classes.text_result_stream.TextResultStream._DisplayAnnotations qm.test.classes.text_result_stream.TextResultStream-class.html#_DisplayAnnotations qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_stream.FileResultStream._argument_dictionary qm.test.file_result_stream.FileResultStream-class.html#_argument_dictionary qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.test.classes.text_result_stream.TextResultStream._DisplayResult qm.test.classes.text_result_stream.TextResultStream-class.html#_DisplayResult qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.file_result_stream.FileResultStream._argument_list qm.test.file_result_stream.FileResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.result_stream.ResultStream.WriteAnnotation qm.test.result_stream.ResultStream-class.html#WriteAnnotation qm.test.classes.thread_target.LocalThread qm.test.classes.thread_target.LocalThread-class.html qm.test.classes.thread_target.LocalThread.GetTemporaryDirectory qm.test.classes.thread_target.LocalThread-class.html#GetTemporaryDirectory qm.test.classes.thread_target.LocalThread.__init__ qm.test.classes.thread_target.LocalThread-class.html#__init__ qm.test.classes.thread_target.LocalThread._RunTest qm.test.classes.thread_target.LocalThread-class.html#_RunTest qm.test.classes.thread_target.ThreadTarget qm.test.classes.thread_target.ThreadTarget-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.thread_target.ThreadTarget.RunTest qm.test.classes.thread_target.ThreadTarget-class.html#RunTest qm.test.classes.thread_target.ThreadTarget.Start qm.test.classes.thread_target.ThreadTarget-class.html#Start qm.test.classes.thread_target.ThreadTarget._BeginResourceSetUp qm.test.classes.thread_target.ThreadTarget-class.html#_BeginResourceSetUp qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.thread_target.ThreadTarget._RunTest qm.test.classes.thread_target.ThreadTarget-class.html#_RunTest qm.test.classes.thread_target.ThreadTarget._RecordResult qm.test.classes.thread_target.ThreadTarget-class.html#_RecordResult qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.thread_target.ThreadTarget.Stop qm.test.classes.thread_target.ThreadTarget-class.html#Stop qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.classes.thread_target.ThreadTarget.arguments qm.test.classes.thread_target.ThreadTarget-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.thread_target.ThreadTarget._GetTemporaryDirectory qm.test.classes.thread_target.ThreadTarget-class.html#_GetTemporaryDirectory qm.test.classes.thread_target.ThreadTarget._FinishResourceSetUp qm.test.classes.thread_target.ThreadTarget-class.html#_FinishResourceSetUp qm.test.classes.thread_target.ThreadTarget._NoteIdleThread qm.test.classes.thread_target.ThreadTarget-class.html#_NoteIdleThread qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.thread_target.ThreadTarget._Trace qm.test.classes.thread_target.ThreadTarget-class.html#_Trace qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.classes.thread_target.ThreadTarget.__init__ qm.test.classes.thread_target.ThreadTarget-class.html#__init__ qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.test.classes.thread_target.ThreadTarget.IsIdle qm.test.classes.thread_target.ThreadTarget-class.html#IsIdle qm.test.classes.xml_database.TestFileError qm.test.classes.xml_database.TestFileError-class.html qm.test.classes.xml_database.XMLDatabase qm.test.classes.xml_database.XMLDatabase-class.html qm.test.classes.xml_database.XMLDatabase.GetAttachmentStore qm.test.classes.xml_database.XMLDatabase-class.html#GetAttachmentStore qm.test.database.Database.modifiable qm.test.database.Database-class.html#modifiable qm.test.database.Database.IsValidLabel qm.test.database.Database-class.html#IsValidLabel qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.database.Database.ExpandIds qm.test.database.Database-class.html#ExpandIds qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.xml_database.XMLDatabase.__LoadItem qm.test.classes.xml_database.XMLDatabase-class.html#__LoadItem qm.test.database.Database.HasResource qm.test.database.Database-class.html#HasResource qm.test.classes.xml_database.XMLDatabase.WriteExtension qm.test.classes.xml_database.XMLDatabase-class.html#WriteExtension qm.test.classes.xml_database.XMLDatabase.__MakeDataFilePath qm.test.classes.xml_database.XMLDatabase-class.html#__MakeDataFilePath qm.test.database.Database.GetSuiteIds qm.test.database.Database-class.html#GetSuiteIds qm.test.database.Database.ITEM_KINDS qm.test.database.Database-class.html#ITEM_KINDS qm.test.database.Database._item_exceptions qm.test.database.Database-class.html#_item_exceptions qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.database.Database.HasTest qm.test.database.Database-class.html#HasTest qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.database.Database.label_class qm.test.database.Database-class.html#label_class qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.database.Database.SplitLabel qm.test.database.Database-class.html#SplitLabel qm.test.database.Database.GetExtension qm.test.database.Database-class.html#GetExtension qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.database.Database._argument_dictionary qm.test.database.Database-class.html#_argument_dictionary qm.test.classes.xml_database.XMLDatabase._GetResourceFromPath qm.test.classes.xml_database.XMLDatabase-class.html#_GetResourceFromPath qm.test.database.Database.JoinLabels qm.test.database.Database-class.html#JoinLabels qm.test.database.Database._is_generic_database qm.test.database.Database-class.html#_is_generic_database qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.database.Database.SplitLabelLeft qm.test.database.Database-class.html#SplitLabelLeft qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.database.Database.GetResourceClassNames qm.test.database.Database-class.html#GetResourceClassNames qm.test.database.Database.SUITE qm.test.database.Database-class.html#SUITE qm.test.database.Database.GetResourceIds qm.test.database.Database-class.html#GetResourceIds qm.test.classes.xml_database.XMLDatabase._GetSuiteFromPath qm.test.classes.xml_database.XMLDatabase-class.html#_GetSuiteFromPath qm.test.database.Database.GetExtensions qm.test.database.Database-class.html#GetExtensions qm.test.database.Database.GetClassPaths qm.test.database.Database-class.html#GetClassPaths qm.test.database.Database.GetPath qm.test.database.Database-class.html#GetPath qm.test.database.Database.GetLabelComponents qm.test.database.Database-class.html#GetLabelComponents qm.test.classes.xml_database.XMLDatabase.__ParseTestDocument qm.test.classes.xml_database.XMLDatabase-class.html#__ParseTestDocument qm.test.database.Database.HasSuite qm.test.database.Database-class.html#HasSuite qm.test.database.Database.kind qm.test.database.Database-class.html#kind qm.test.classes.xml_database.XMLDatabase._GetTestFromPath qm.test.classes.xml_database.XMLDatabase-class.html#_GetTestFromPath qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.xml_database.XMLDatabase.__init__ qm.test.classes.xml_database.XMLDatabase-class.html#__init__ qm.test.database.Database.RESOURCE qm.test.database.Database-class.html#RESOURCE qm.test.classes.xml_database.XMLDatabase.__StoreAttachments qm.test.classes.xml_database.XMLDatabase-class.html#__StoreAttachments qm.test.database.Database.GetConfigurationDirectory qm.test.database.Database-class.html#GetConfigurationDirectory qm.test.classes.xml_database.XMLDatabase.__ParseResourceDocument qm.test.classes.xml_database.XMLDatabase-class.html#__ParseResourceDocument qm.test.database.Database.GetTestIds qm.test.database.Database-class.html#GetTestIds qm.test.database.Database.GetTestClassNames qm.test.database.Database-class.html#GetTestClassNames qm.test.database.Database.IsModifiable qm.test.database.Database-class.html#IsModifiable qm.test.classes.xml_database.XMLDatabase._Trace qm.test.classes.xml_database.XMLDatabase-class.html#_Trace qm.test.database.Database.GetItem qm.test.database.Database-class.html#GetItem qm.test.database.Database._argument_list qm.test.database.Database-class.html#_argument_list qm.test.database.Database.TEST qm.test.database.Database-class.html#TEST qm.test.classes.xml_expectation_database.XMLExpectationDatabase qm.test.classes.xml_expectation_database.XMLExpectationDatabase-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.classes.xml_expectation_database.XMLExpectationDatabase.file_name qm.test.classes.xml_expectation_database.XMLExpectationDatabase-class.html#file_name qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.classes.xml_expectation_database.XMLExpectationDatabase.Lookup qm.test.classes.xml_expectation_database.XMLExpectationDatabase-class.html#Lookup qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.xml_expectation_database.XMLExpectationDatabase.__init__ qm.test.classes.xml_expectation_database.XMLExpectationDatabase-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.xml_result_stream.XMLResultReader qm.test.classes.xml_result_stream.XMLResultReader-class.html qm.test.classes.xml_result_stream.XMLResultReader.GetAnnotations qm.test.classes.xml_result_stream.XMLResultReader-class.html#GetAnnotations qm.test.file_result_reader.FileResultReader._is_binary_file qm.test.file_result_reader.FileResultReader-class.html#_is_binary_file qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.file_result_reader.FileResultReader.file qm.test.file_result_reader.FileResultReader-class.html#file qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.xml_result_stream.XMLResultReader.__init__ qm.test.classes.xml_result_stream.XMLResultReader-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.file_result_reader.FileResultReader.InvalidFile qm.test.file_result_reader.FileResultReader.InvalidFile-class.html qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_reader.FileResultReader.filename qm.test.file_result_reader.FileResultReader-class.html#filename qm.test.file_result_reader.FileResultReader.arguments qm.test.file_result_reader.FileResultReader-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.classes.xml_result_stream.XMLResultReader._GetResultFromDomNode qm.test.classes.xml_result_stream.XMLResultReader-class.html#_GetResultFromDomNode qm.test.classes.xml_result_stream.XMLResultReader.GetResult qm.test.classes.xml_result_stream.XMLResultReader-class.html#GetResult qm.test.result_reader.ResultReader.__iter__ qm.test.result_reader.ResultReader-class.html#__iter__ qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_reader.FileResultReader._argument_dictionary qm.test.file_result_reader.FileResultReader-class.html#_argument_dictionary qm.test.result_reader.ResultReader.kind qm.test.result_reader.ResultReader-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.file_result_reader.FileResultReader._argument_list qm.test.file_result_reader.FileResultReader-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.xml_result_stream.XMLResultStream qm.test.classes.xml_result_stream.XMLResultStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.file_result_stream.FileResultStream.file qm.test.file_result_stream.FileResultStream-class.html#file qm.test.file_result_stream.FileResultStream.filename qm.test.file_result_stream.FileResultStream-class.html#filename qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.classes.xml_result_stream.XMLResultStream.__init__ qm.test.classes.xml_result_stream.XMLResultStream-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.classes.xml_result_stream.XMLResultStream.WriteResult qm.test.classes.xml_result_stream.XMLResultStream-class.html#WriteResult qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_stream.FileResultStream._is_binary_file qm.test.file_result_stream.FileResultStream-class.html#_is_binary_file qm.test.file_result_stream.FileResultStream.arguments qm.test.file_result_stream.FileResultStream-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.classes.xml_result_stream.XMLResultStream.Summarize qm.test.classes.xml_result_stream.XMLResultStream-class.html#Summarize qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_stream.FileResultStream._argument_dictionary qm.test.file_result_stream.FileResultStream-class.html#_argument_dictionary qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.file_result_stream.FileResultStream._argument_list qm.test.file_result_stream.FileResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.classes.xml_result_stream.XMLResultStream.WriteAnnotation qm.test.classes.xml_result_stream.XMLResultStream-class.html#WriteAnnotation qm.test.cmdline.QMTest qm.test.cmdline.QMTest-class.html qm.test.cmdline.QMTest.GetDatabase qm.test.cmdline.QMTest-class.html#GetDatabase qm.test.cmdline.QMTest.GetFileResultStreamClass qm.test.cmdline.QMTest-class.html#GetFileResultStreamClass qm.test.cmdline.QMTest.__ExecuteReport qm.test.cmdline.QMTest-class.html#__ExecuteReport qm.test.cmdline.QMTest.__FilterTestsToRun qm.test.cmdline.QMTest-class.html#__FilterTestsToRun qm.test.cmdline.QMTest.expectations_file_name qm.test.cmdline.QMTest-class.html#expectations_file_name qm.test.cmdline.QMTest.attribute_option_spec qm.test.cmdline.QMTest-class.html#attribute_option_spec qm.test.cmdline.QMTest.GetCommandOption qm.test.cmdline.QMTest-class.html#GetCommandOption qm.test.cmdline.QMTest.__extension_kinds_string qm.test.cmdline.QMTest-class.html#__extension_kinds_string qm.test.cmdline.QMTest.HasGlobalOption qm.test.cmdline.QMTest-class.html#HasGlobalOption qm.test.cmdline.QMTest.GetTargetsFromFile qm.test.cmdline.QMTest-class.html#GetTargetsFromFile qm.test.cmdline.QMTest.port_option_spec qm.test.cmdline.QMTest-class.html#port_option_spec qm.test.cmdline.QMTest.format_option_spec qm.test.cmdline.QMTest-class.html#format_option_spec qm.test.cmdline.QMTest.__ExecuteExtensions qm.test.cmdline.QMTest-class.html#__ExecuteExtensions qm.test.cmdline.QMTest.summary_formats qm.test.cmdline.QMTest-class.html#summary_formats qm.test.cmdline.QMTest.concurrent_option_spec qm.test.cmdline.QMTest-class.html#concurrent_option_spec qm.test.cmdline.QMTest.no_output_option_spec qm.test.cmdline.QMTest-class.html#no_output_option_spec qm.test.cmdline.QMTest.__ExecuteRegister qm.test.cmdline.QMTest-class.html#__ExecuteRegister qm.test.cmdline.QMTest.__ExecuteRun qm.test.cmdline.QMTest-class.html#__ExecuteRun qm.test.cmdline.QMTest.__ExecuteCreateTarget qm.test.cmdline.QMTest-class.html#__ExecuteCreateTarget qm.test.cmdline.QMTest.__WriteCommandHelp qm.test.cmdline.QMTest-class.html#__WriteCommandHelp qm.test.cmdline.QMTest.annotation_option_spec qm.test.cmdline.QMTest-class.html#annotation_option_spec qm.test.cmdline.QMTest.__GetAttributeOptions qm.test.cmdline.QMTest-class.html#__GetAttributeOptions qm.test.cmdline.QMTest.__GetAnnotateOptions qm.test.cmdline.QMTest-class.html#__GetAnnotateOptions qm.test.cmdline.QMTest.log_file_option_spec qm.test.cmdline.QMTest-class.html#log_file_option_spec qm.test.cmdline.QMTest.GetTracer qm.test.cmdline.QMTest-class.html#GetTracer qm.test.cmdline.QMTest.output_option_spec qm.test.cmdline.QMTest-class.html#output_option_spec qm.test.cmdline.QMTest.GetDatabaseIfAvailable qm.test.cmdline.QMTest-class.html#GetDatabaseIfAvailable qm.test.cmdline.QMTest.conflicting_option_specs qm.test.cmdline.QMTest-class.html#conflicting_option_specs qm.test.cmdline.QMTest.__ExecuteServer qm.test.cmdline.QMTest-class.html#__ExecuteServer qm.test.cmdline.QMTest.seed_option_spec qm.test.cmdline.QMTest-class.html#seed_option_spec qm.test.cmdline.QMTest.context_file_name qm.test.cmdline.QMTest-class.html#context_file_name qm.test.cmdline.QMTest.__ExecuteRemote qm.test.cmdline.QMTest-class.html#__ExecuteRemote qm.test.cmdline.QMTest.targets_option_spec qm.test.cmdline.QMTest-class.html#targets_option_spec qm.test.cmdline.QMTest.HasCommandOption qm.test.cmdline.QMTest-class.html#HasCommandOption qm.test.cmdline.QMTest.commands_spec qm.test.cmdline.QMTest-class.html#commands_spec qm.test.cmdline.QMTest.Execute qm.test.cmdline.QMTest-class.html#Execute qm.test.cmdline.QMTest.__CheckExtensionKind qm.test.cmdline.QMTest-class.html#__CheckExtensionKind qm.test.cmdline.QMTest.db_path_option_spec qm.test.cmdline.QMTest-class.html#db_path_option_spec qm.test.cmdline.QMTest.results_file_name qm.test.cmdline.QMTest-class.html#results_file_name qm.test.cmdline.QMTest.__del__ qm.test.cmdline.QMTest-class.html#__del__ qm.test.cmdline.QMTest.version_option_spec qm.test.cmdline.QMTest-class.html#version_option_spec qm.test.cmdline.QMTest.GetExecutablePath qm.test.cmdline.QMTest-class.html#GetExecutablePath qm.test.cmdline.QMTest.extension_output_option_spec qm.test.cmdline.QMTest-class.html#extension_output_option_spec qm.test.cmdline.QMTest.GetTargets qm.test.cmdline.QMTest-class.html#GetTargets qm.test.cmdline.QMTest.results_option_spec qm.test.cmdline.QMTest-class.html#results_option_spec qm.test.cmdline.QMTest.__CreateResultStreams qm.test.cmdline.QMTest-class.html#__CreateResultStreams qm.test.cmdline.QMTest.rerun_option_spec qm.test.cmdline.QMTest-class.html#rerun_option_spec qm.test.cmdline.QMTest.__version_output qm.test.cmdline.QMTest-class.html#__version_output qm.test.cmdline.QMTest.GetTargetFileName qm.test.cmdline.QMTest-class.html#GetTargetFileName qm.test.cmdline.QMTest.daemon_option_spec qm.test.cmdline.QMTest-class.html#daemon_option_spec qm.test.cmdline.QMTest.GetTextResultStreamClass qm.test.cmdline.QMTest-class.html#GetTextResultStreamClass qm.test.cmdline.QMTest.pid_file_option_spec qm.test.cmdline.QMTest-class.html#pid_file_option_spec qm.test.cmdline.QMTest.help_option_spec qm.test.cmdline.QMTest-class.html#help_option_spec qm.test.cmdline.QMTest.__ExecuteSummarize qm.test.cmdline.QMTest-class.html#__ExecuteSummarize qm.test.cmdline.QMTest.db_path_environment_variable qm.test.cmdline.QMTest-class.html#db_path_environment_variable qm.test.cmdline.QMTest.target_file_name qm.test.cmdline.QMTest-class.html#target_file_name qm.test.cmdline.QMTest.list_recursive_option_spec qm.test.cmdline.QMTest-class.html#list_recursive_option_spec qm.test.cmdline.QMTest.__ExecuteCreate qm.test.cmdline.QMTest-class.html#__ExecuteCreate qm.test.cmdline.QMTest.report_flat_option_spec qm.test.cmdline.QMTest-class.html#report_flat_option_spec qm.test.cmdline.QMTest.__ExecuteDescribe qm.test.cmdline.QMTest-class.html#__ExecuteDescribe qm.test.cmdline.QMTest.list_details_option_spec qm.test.cmdline.QMTest-class.html#list_details_option_spec qm.test.cmdline.QMTest.__ExecuteList qm.test.cmdline.QMTest-class.html#__ExecuteList qm.test.cmdline.QMTest.context_option_spec qm.test.cmdline.QMTest-class.html#context_option_spec qm.test.cmdline.QMTest.report_output_option_spec qm.test.cmdline.QMTest-class.html#report_output_option_spec qm.test.cmdline.QMTest.extension_kind_option_spec qm.test.cmdline.QMTest-class.html#extension_kind_option_spec qm.test.cmdline.QMTest.random_option_spec qm.test.cmdline.QMTest-class.html#random_option_spec qm.test.cmdline.QMTest.__ExecuteCreateTdb qm.test.cmdline.QMTest-class.html#__ExecuteCreateTdb qm.test.cmdline.QMTest.no_browser_option_spec qm.test.cmdline.QMTest-class.html#no_browser_option_spec qm.test.cmdline.QMTest.context_file_spec qm.test.cmdline.QMTest-class.html#context_file_spec qm.test.cmdline.QMTest.__init__ qm.test.cmdline.QMTest-class.html#__init__ qm.test.cmdline.QMTest.expectations_option_spec qm.test.cmdline.QMTest-class.html#expectations_option_spec qm.test.cmdline.QMTest.MakeContext qm.test.cmdline.QMTest-class.html#MakeContext qm.test.cmdline.QMTest.GetGlobalOption qm.test.cmdline.QMTest-class.html#GetGlobalOption qm.test.cmdline.QMTest.set_attribute_option_spec qm.test.cmdline.QMTest-class.html#set_attribute_option_spec qm.test.cmdline.QMTest.global_options_spec qm.test.cmdline.QMTest-class.html#global_options_spec qm.test.cmdline.QMTest.tdb_class_option_spec qm.test.cmdline.QMTest-class.html#tdb_class_option_spec qm.test.cmdline.QMTest.outcomes_option_spec qm.test.cmdline.QMTest-class.html#outcomes_option_spec qm.test.cmdline.QMTest.result_stream_spec qm.test.cmdline.QMTest-class.html#result_stream_spec qm.test.cmdline.QMTest.extension_id_option_spec qm.test.cmdline.QMTest-class.html#extension_id_option_spec qm.test.cmdline.QMTest.address_option_spec qm.test.cmdline.QMTest-class.html#address_option_spec qm.test.cmdline.QMTest.list_long_option_spec qm.test.cmdline.QMTest-class.html#list_long_option_spec qm.test.command_thread.CommandThread qm.test.command_thread.CommandThread-class.html qm.test.command_thread.CommandThread.RunTest qm.test.command_thread.CommandThread-class.html#RunTest qm.test.command_thread.CommandThread._RunTest qm.test.command_thread.CommandThread-class.html#_RunTest qm.test.command_thread.CommandThread.Stop qm.test.command_thread.CommandThread-class.html#Stop qm.test.command_thread.CommandThread.GetTarget qm.test.command_thread.CommandThread-class.html#GetTarget qm.test.command_thread.CommandThread.__init__ qm.test.command_thread.CommandThread-class.html#__init__ qm.test.command_thread.CommandThread.run qm.test.command_thread.CommandThread-class.html#run qm.test.command_thread.CommandThread._Trace qm.test.command_thread.CommandThread-class.html#_Trace qm.test.command_thread.CommandThread._Stop qm.test.command_thread.CommandThread-class.html#_Stop qm.test.context.Context qm.test.context.Context-class.html qm.test.context.Context.GetAddedProperties qm.test.context.Context-class.html#GetAddedProperties qm.test.context.Context.GetTemporaryDirectory qm.test.context.Context-class.html#GetTemporaryDirectory qm.test.context.Context.has_key qm.test.context.Context-class.html#has_key qm.test.context.Context.DB_PATH_CONTEXT_PROPERTY qm.test.context.Context-class.html#DB_PATH_CONTEXT_PROPERTY qm.test.context.Context.GetDerivedValue qm.test.context.Context-class.html#GetDerivedValue qm.test.context.Context.__init__ qm.test.context.Context-class.html#__init__ qm.test.context.Context.GetBoolean qm.test.context.Context-class.html#GetBoolean qm.test.context.Context.__getitem__ qm.test.context.Context-class.html#__getitem__ qm.test.context.Context.__contains__ qm.test.context.Context-class.html#__contains__ qm.test.context.Context.Read qm.test.context.Context-class.html#Read qm.test.context.Context.GetStringList qm.test.context.Context-class.html#GetStringList qm.test.context.Context.ID_CONTEXT_PROPERTY qm.test.context.Context-class.html#ID_CONTEXT_PROPERTY qm.test.context.Context.TMPDIR_CONTEXT_PROPERTY qm.test.context.Context-class.html#TMPDIR_CONTEXT_PROPERTY qm.test.context.Context.TARGET_CONTEXT_PROPERTY qm.test.context.Context-class.html#TARGET_CONTEXT_PROPERTY qm.test.context.Context.get qm.test.context.Context-class.html#get qm.test.context.Context.items qm.test.context.Context-class.html#items qm.test.context.Context.__safe_for_unpickling__ qm.test.context.Context-class.html#__safe_for_unpickling__ qm.test.context.ContextException qm.test.context.ContextException-class.html qm.test.context.ContextException.__init__ qm.test.context.ContextException-class.html#__init__ qm.test.context.ContextWrapper qm.test.context.ContextWrapper-class.html qm.test.database.Database qm.test.database.Database-class.html qm.test.database.Database.GetAttachmentStore qm.test.database.Database-class.html#GetAttachmentStore qm.test.database.Database.modifiable qm.test.database.Database-class.html#modifiable qm.test.database.Database.GetResourceClassNames qm.test.database.Database-class.html#GetResourceClassNames qm.test.database.Database.GetTest qm.test.database.Database-class.html#GetTest qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.database.Database.RemoveExtension qm.test.database.Database-class.html#RemoveExtension qm.test.database.Database.HasTest qm.test.database.Database-class.html#HasTest qm.test.database.Database.GetSuite qm.test.database.Database-class.html#GetSuite qm.test.database.Database.SUITE qm.test.database.Database-class.html#SUITE qm.test.database.Database.ExpandIds qm.test.database.Database-class.html#ExpandIds qm.test.database.Database.IsValidLabel qm.test.database.Database-class.html#IsValidLabel qm.test.database.Database.__init__ qm.test.database.Database-class.html#__init__ qm.test.database.Database.GetResourceIds qm.test.database.Database-class.html#GetResourceIds qm.test.database.Database.RESOURCE qm.test.database.Database-class.html#RESOURCE qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.database.Database.JoinLabels qm.test.database.Database-class.html#JoinLabels qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.database.Database.GetResource qm.test.database.Database-class.html#GetResource qm.test.database.Database.label_class qm.test.database.Database-class.html#label_class qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.database.Database.GetExtensions qm.test.database.Database-class.html#GetExtensions qm.test.database.Database.SplitLabel qm.test.database.Database-class.html#SplitLabel qm.test.database.Database.GetSubdirectories qm.test.database.Database-class.html#GetSubdirectories qm.test.database.Database.arguments qm.test.database.Database-class.html#arguments qm.test.database.Database.GetConfigurationDirectory qm.test.database.Database-class.html#GetConfigurationDirectory qm.test.database.Database.GetTestIds qm.test.database.Database-class.html#GetTestIds qm.test.database.Database.GetClassPaths qm.test.database.Database-class.html#GetClassPaths qm.test.database.Database.HasResource qm.test.database.Database-class.html#HasResource qm.test.database.Database.GetTestClassNames qm.test.database.Database-class.html#GetTestClassNames qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.database.Database.WriteExtension qm.test.database.Database-class.html#WriteExtension qm.test.database.Database.SplitLabelLeft qm.test.database.Database-class.html#SplitLabelLeft qm.test.database.Database.GetPath qm.test.database.Database-class.html#GetPath qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.database.Database.IsModifiable qm.test.database.Database-class.html#IsModifiable qm.test.database.Database.GetIds qm.test.database.Database-class.html#GetIds qm.test.database.Database.GetSuiteIds qm.test.database.Database-class.html#GetSuiteIds qm.test.database.Database.GetExtension qm.test.database.Database-class.html#GetExtension qm.test.database.Database.GetLabelComponents qm.test.database.Database-class.html#GetLabelComponents qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.database.Database.HasSuite qm.test.database.Database-class.html#HasSuite qm.test.database.Database._argument_dictionary qm.test.database.Database-class.html#_argument_dictionary qm.test.database.Database.kind qm.test.database.Database-class.html#kind qm.test.database.Database.ITEM_KINDS qm.test.database.Database-class.html#ITEM_KINDS qm.test.database.Database._item_exceptions qm.test.database.Database-class.html#_item_exceptions qm.test.database.Database._is_generic_database qm.test.database.Database-class.html#_is_generic_database qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.database.Database.GetItem qm.test.database.Database-class.html#GetItem qm.test.database.Database._argument_list qm.test.database.Database-class.html#_argument_list qm.test.database.Database.TEST qm.test.database.Database-class.html#TEST qm.test.database.DatabaseError qm.test.database.DatabaseError-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.test.database.ItemDescriptor qm.test.database.ItemDescriptor-class.html qm.test.database.ItemDescriptor.GetDatabase qm.test.database.ItemDescriptor-class.html#GetDatabase qm.test.database.ItemDescriptor.GetClassArguments qm.test.database.ItemDescriptor-class.html#GetClassArguments qm.test.database.ItemDescriptor.GetClass qm.test.database.ItemDescriptor-class.html#GetClass qm.test.database.ItemDescriptor._Execute qm.test.database.ItemDescriptor-class.html#_Execute qm.test.database.ItemDescriptor.GetId qm.test.database.ItemDescriptor-class.html#GetId qm.test.database.ItemDescriptor.GetArguments qm.test.database.ItemDescriptor-class.html#GetArguments qm.test.database.ItemDescriptor.GetItem qm.test.database.ItemDescriptor-class.html#GetItem qm.test.database.ItemDescriptor.GetClassName qm.test.database.ItemDescriptor-class.html#GetClassName qm.test.database.ItemDescriptor.__init__ qm.test.database.ItemDescriptor-class.html#__init__ qm.test.database.ItemDescriptor.GetResources qm.test.database.ItemDescriptor-class.html#GetResources qm.test.database.NoSuchItemError qm.test.database.NoSuchItemError-class.html qm.test.database.NoSuchItemError.__str__ qm.test.database.NoSuchItemError-class.html#__str__ qm.test.database.NoSuchItemError.__init__ qm.test.database.NoSuchItemError-class.html#__init__ qm.test.database.NoSuchResourceError qm.test.database.NoSuchResourceError-class.html qm.test.database.NoSuchItemError.__str__ qm.test.database.NoSuchItemError-class.html#__str__ qm.test.database.NoSuchResourceError.__init__ qm.test.database.NoSuchResourceError-class.html#__init__ qm.test.database.NoSuchSuiteError qm.test.database.NoSuchSuiteError-class.html qm.test.database.NoSuchItemError.__str__ qm.test.database.NoSuchItemError-class.html#__str__ qm.test.database.NoSuchSuiteError.__init__ qm.test.database.NoSuchSuiteError-class.html#__init__ qm.test.database.NoSuchTestError qm.test.database.NoSuchTestError-class.html qm.test.database.NoSuchItemError.__str__ qm.test.database.NoSuchItemError-class.html#__str__ qm.test.database.NoSuchTestError.__init__ qm.test.database.NoSuchTestError-class.html#__init__ qm.test.database.ResourceDescriptor qm.test.database.ResourceDescriptor-class.html qm.test.database.ItemDescriptor.GetDatabase qm.test.database.ItemDescriptor-class.html#GetDatabase qm.test.database.ItemDescriptor.GetClassArguments qm.test.database.ItemDescriptor-class.html#GetClassArguments qm.test.database.ResourceDescriptor.GetClass qm.test.database.ResourceDescriptor-class.html#GetClass qm.test.database.ItemDescriptor._Execute qm.test.database.ItemDescriptor-class.html#_Execute qm.test.database.ResourceDescriptor.SetUp qm.test.database.ResourceDescriptor-class.html#SetUp qm.test.database.ResourceDescriptor.GetResource qm.test.database.ResourceDescriptor-class.html#GetResource qm.test.database.ItemDescriptor.GetId qm.test.database.ItemDescriptor-class.html#GetId qm.test.database.ResourceDescriptor.CleanUp qm.test.database.ResourceDescriptor-class.html#CleanUp qm.test.database.ItemDescriptor.GetArguments qm.test.database.ItemDescriptor-class.html#GetArguments qm.test.database.ItemDescriptor.GetItem qm.test.database.ItemDescriptor-class.html#GetItem qm.test.database.ItemDescriptor.GetClassName qm.test.database.ItemDescriptor-class.html#GetClassName qm.test.database.ResourceDescriptor.__init__ qm.test.database.ResourceDescriptor-class.html#__init__ qm.test.database.ItemDescriptor.GetResources qm.test.database.ItemDescriptor-class.html#GetResources qm.test.database.TestDescriptor qm.test.database.TestDescriptor-class.html qm.test.database.ItemDescriptor.GetDatabase qm.test.database.ItemDescriptor-class.html#GetDatabase qm.test.database.ItemDescriptor.GetClassArguments qm.test.database.ItemDescriptor-class.html#GetClassArguments qm.test.database.TestDescriptor.Run qm.test.database.TestDescriptor-class.html#Run qm.test.database.ItemDescriptor._Execute qm.test.database.ItemDescriptor-class.html#_Execute qm.test.database.TestDescriptor.GetPrerequisites qm.test.database.TestDescriptor-class.html#GetPrerequisites qm.test.database.TestDescriptor.GetTargetGroup qm.test.database.TestDescriptor-class.html#GetTargetGroup qm.test.database.ItemDescriptor.GetId qm.test.database.ItemDescriptor-class.html#GetId qm.test.database.TestDescriptor.GetTest qm.test.database.TestDescriptor-class.html#GetTest qm.test.database.ItemDescriptor.GetArguments qm.test.database.ItemDescriptor-class.html#GetArguments qm.test.database.ItemDescriptor.GetItem qm.test.database.ItemDescriptor-class.html#GetItem qm.test.database.ItemDescriptor.GetClassName qm.test.database.ItemDescriptor-class.html#GetClassName qm.test.database.TestDescriptor.GetClass qm.test.database.TestDescriptor-class.html#GetClass qm.test.database.TestDescriptor.__init__ qm.test.database.TestDescriptor-class.html#__init__ qm.test.database.ItemDescriptor.GetResources qm.test.database.ItemDescriptor-class.html#GetResources qm.test.directory_suite.DirectorySuite qm.test.directory_suite.DirectorySuite-class.html qm.test.suite.Suite.GetAllTestAndSuiteIds qm.test.suite.Suite-class.html#GetAllTestAndSuiteIds qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.directory_suite.DirectorySuite.__init__ qm.test.directory_suite.DirectorySuite-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.directory_suite.DirectorySuite.IsImplicit qm.test.directory_suite.DirectorySuite-class.html#IsImplicit qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.suite.Suite.arguments qm.test.suite.Suite-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.directory_suite.DirectorySuite.GetTestIds qm.test.directory_suite.DirectorySuite-class.html#GetTestIds qm.test.suite.Suite.GetDatabase qm.test.suite.Suite-class.html#GetDatabase qm.test.suite.Suite.GetId qm.test.suite.Suite-class.html#GetId qm.test.directory_suite.DirectorySuite.GetSuiteIds qm.test.directory_suite.DirectorySuite-class.html#GetSuiteIds qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.suite.Suite.kind qm.test.suite.Suite-class.html#kind qm.test.suite.Suite.EXTRA_DATABASE qm.test.suite.Suite-class.html#EXTRA_DATABASE qm.test.suite.Suite.EXTRA_ID qm.test.suite.Suite-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.execution_engine.ExecutionEngine qm.test.execution_engine.ExecutionEngine-class.html qm.test.execution_engine.ExecutionEngine.AddInputHandler qm.test.execution_engine.ExecutionEngine-class.html#AddInputHandler qm.test.execution_engine.ExecutionEngine.__TARGET_STARVING qm.test.execution_engine.ExecutionEngine-class.html#__TARGET_STARVING qm.test.execution_engine.ExecutionEngine.Run qm.test.execution_engine.ExecutionEngine-class.html#Run qm.test.execution_engine.ExecutionEngine.RequestTermination qm.test.execution_engine.ExecutionEngine-class.html#RequestTermination qm.test.execution_engine.ExecutionEngine._WriteInitialAnnotations qm.test.execution_engine.ExecutionEngine-class.html#_WriteInitialAnnotations qm.test.execution_engine.ExecutionEngine.__AddResult qm.test.execution_engine.ExecutionEngine-class.html#__AddResult qm.test.execution_engine.ExecutionEngine._Trace qm.test.execution_engine.ExecutionEngine-class.html#_Trace qm.test.execution_engine.ExecutionEngine.__GetPendingPrerequisites qm.test.execution_engine.ExecutionEngine-class.html#__GetPendingPrerequisites qm.test.execution_engine.ExecutionEngine.__GetTestDescriptor qm.test.execution_engine.ExecutionEngine-class.html#__GetTestDescriptor qm.test.execution_engine.ExecutionEngine.__CheckForResponse qm.test.execution_engine.ExecutionEngine-class.html#__CheckForResponse qm.test.execution_engine.ExecutionEngine.__TARGET_BUSY qm.test.execution_engine.ExecutionEngine-class.html#__TARGET_BUSY qm.test.execution_engine.ExecutionEngine.__TARGET_IDLE qm.test.execution_engine.ExecutionEngine-class.html#__TARGET_IDLE qm.test.execution_engine.ExecutionEngine.__AddTestToStack qm.test.execution_engine.ExecutionEngine-class.html#__AddTestToStack qm.test.execution_engine.ExecutionEngine.__FindRunnableTest qm.test.execution_engine.ExecutionEngine-class.html#__FindRunnableTest qm.test.execution_engine.ExecutionEngine._RunTests qm.test.execution_engine.ExecutionEngine-class.html#_RunTests qm.test.execution_engine.ExecutionEngine.__FeedTarget qm.test.execution_engine.ExecutionEngine-class.html#__FeedTarget qm.test.execution_engine.ExecutionEngine._IsTerminationRequested qm.test.execution_engine.ExecutionEngine-class.html#_IsTerminationRequested qm.test.execution_engine.ExecutionEngine.__TestStatus qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html qm.test.execution_engine.ExecutionEngine.__AddToTargetPatternQueue qm.test.execution_engine.ExecutionEngine-class.html#__AddToTargetPatternQueue qm.test.execution_engine.ExecutionEngine.__init__ qm.test.execution_engine.ExecutionEngine-class.html#__init__ qm.test.execution_engine.ExecutionEngine.__AddUntestedResult qm.test.execution_engine.ExecutionEngine-class.html#__AddUntestedResult qm.test.execution_engine.ExecutionEngine.__TestStatus qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html qm.test.execution_engine.ExecutionEngine.__TestStatus.GetState qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#GetState qm.test.execution_engine.ExecutionEngine.__TestStatus.HasBeenQueued qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#HasBeenQueued qm.test.execution_engine.ExecutionEngine.__TestStatus.HasBeenReady qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#HasBeenReady qm.test.execution_engine.ExecutionEngine.__TestStatus.NoteQueued qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#NoteQueued qm.test.execution_engine.ExecutionEngine.__TestStatus.NoteReady qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#NoteReady qm.test.execution_engine.ExecutionEngine.__TestStatus.IsFinished qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#IsFinished qm.test.execution_engine.ExecutionEngine.__TestStatus.NoteDependant qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#NoteDependant qm.test.execution_engine.ExecutionEngine.__TestStatus.READY qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#READY qm.test.execution_engine.ExecutionEngine.__TestStatus.QUEUED qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#QUEUED qm.test.execution_engine.ExecutionEngine.__TestStatus.__init__ qm.test.execution_engine.ExecutionEngine.__TestStatus-class.html#__init__ qm.test.execution_engine.TerminationRequested qm.test.execution_engine.TerminationRequested-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.test.execution_thread.ExecutionThread qm.test.execution_thread.ExecutionThread-class.html qm.test.execution_thread.ExecutionThread.run qm.test.execution_thread.ExecutionThread-class.html#run qm.test.execution_thread.ExecutionThread.__init__ qm.test.execution_thread.ExecutionThread-class.html#__init__ qm.test.execution_thread.ExecutionThread.RequestTermination qm.test.execution_thread.ExecutionThread-class.html#RequestTermination qm.test.execution_thread.ExecutionThread._IsTerminationRequested qm.test.execution_thread.ExecutionThread-class.html#_IsTerminationRequested qm.test.expectation_database.ExpectationDatabase qm.test.expectation_database.ExpectationDatabase-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.expectation_database.ExpectationDatabase.Lookup qm.test.expectation_database.ExpectationDatabase-class.html#Lookup qm.test.expectation_database.ExpectationDatabase.test_database qm.test.expectation_database.ExpectationDatabase-class.html#test_database qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.extension.Extension.__init__ qm.extension.Extension-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.expectation_database.ExpectationDatabase.testrun_parameters qm.test.expectation_database.ExpectationDatabase-class.html#testrun_parameters qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.expectation_database.ExpectationDatabase._argument_dictionary qm.test.expectation_database.ExpectationDatabase-class.html#_argument_dictionary qm.test.expectation_database.ExpectationDatabase.GetExpectedOutcomes qm.test.expectation_database.ExpectationDatabase-class.html#GetExpectedOutcomes qm.test.expectation_database.ExpectationDatabase.kind qm.test.expectation_database.ExpectationDatabase-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.expectation_database.ExpectationDatabase._argument_list qm.test.expectation_database.ExpectationDatabase-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.file_database.ExtensionDatabase qm.test.file_database.ExtensionDatabase-class.html qm.test.database.Database.GetLabelComponents qm.test.database.Database-class.html#GetLabelComponents qm.test.file_database.ExtensionDatabase._GetLabelFromBasename qm.test.file_database.ExtensionDatabase-class.html#_GetLabelFromBasename qm.test.file_database.FileDatabase.GetRoot qm.test.file_database.FileDatabase-class.html#GetRoot qm.test.database.Database.GetAttachmentStore qm.test.database.Database-class.html#GetAttachmentStore qm.test.file_database.FileDatabase._AreLabelsPaths qm.test.file_database.FileDatabase-class.html#_AreLabelsPaths qm.test.database.Database.GetTestClassNames qm.test.database.Database-class.html#GetTestClassNames qm.test.database.Database.modifiable qm.test.database.Database-class.html#modifiable qm.test.database.Database.GetResourceClassNames qm.test.database.Database-class.html#GetResourceClassNames qm.test.file_database.FileDatabase.GetTest qm.test.file_database.FileDatabase-class.html#GetTest qm.test.file_database.FileDatabase._GetPath qm.test.file_database.FileDatabase-class.html#_GetPath qm.test.file_database.FileDatabase.RemoveExtension qm.test.file_database.FileDatabase-class.html#RemoveExtension qm.test.file_database.ExtensionDatabase.GetResourcePath qm.test.file_database.ExtensionDatabase-class.html#GetResourcePath qm.test.database.Database.HasTest qm.test.database.Database-class.html#HasTest qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_database.FileDatabase.GetSuite qm.test.file_database.FileDatabase-class.html#GetSuite qm.test.database.Database.SUITE qm.test.database.Database-class.html#SUITE qm.test.database.Database.GetExtensions qm.test.database.Database-class.html#GetExtensions qm.test.database.Database.IsValidLabel qm.test.database.Database-class.html#IsValidLabel qm.test.file_database.ExtensionDatabase.__init__ qm.test.file_database.ExtensionDatabase-class.html#__init__ qm.test.database.Database.GetResourceIds qm.test.database.Database-class.html#GetResourceIds qm.test.database.Database.SplitLabel qm.test.database.Database-class.html#SplitLabel qm.test.file_database.ExtensionDatabase.test_extension qm.test.file_database.ExtensionDatabase-class.html#test_extension qm.test.file_database.ExtensionDatabase.suite_extension qm.test.file_database.ExtensionDatabase-class.html#suite_extension qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.file_database.FileDatabase._GetSuiteFromPath qm.test.file_database.FileDatabase-class.html#_GetSuiteFromPath qm.test.database.Database.GetSuiteIds qm.test.database.Database-class.html#GetSuiteIds qm.test.file_database.FileDatabase.GetResource qm.test.file_database.FileDatabase-class.html#GetResource qm.test.database.Database.label_class qm.test.database.Database-class.html#label_class qm.test.database.Database.ITEM_KINDS qm.test.database.Database-class.html#ITEM_KINDS qm.test.database.Database.ExpandIds qm.test.database.Database-class.html#ExpandIds qm.test.file_database.FileDatabase._IsFile qm.test.file_database.FileDatabase-class.html#_IsFile qm.test.file_database.FileDatabase.GetSubdirectories qm.test.file_database.FileDatabase-class.html#GetSubdirectories qm.test.file_database.ExtensionDatabase.arguments qm.test.file_database.ExtensionDatabase-class.html#arguments qm.test.database.Database.GetConfigurationDirectory qm.test.database.Database-class.html#GetConfigurationDirectory qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.file_database.ExtensionDatabase.GetResourceExtension qm.test.file_database.ExtensionDatabase-class.html#GetResourceExtension qm.test.database.Database.GetTestIds qm.test.database.Database-class.html#GetTestIds qm.test.database.Database.GetClassPaths qm.test.database.Database-class.html#GetClassPaths qm.test.database.Database.HasResource qm.test.database.Database-class.html#HasResource qm.test.file_database.ExtensionDatabase.GetSuitePath qm.test.file_database.ExtensionDatabase-class.html#GetSuitePath qm.test.file_database.ExtensionDatabase._IsTestFile qm.test.file_database.ExtensionDatabase-class.html#_IsTestFile qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.file_database.ExtensionDatabase._IsResourceFile qm.test.file_database.ExtensionDatabase-class.html#_IsResourceFile qm.test.file_database.ExtensionDatabase.GetTestExtension qm.test.file_database.ExtensionDatabase-class.html#GetTestExtension qm.test.file_database.ExtensionDatabase.resource_extension qm.test.file_database.ExtensionDatabase-class.html#resource_extension qm.test.database.Database.GetPath qm.test.database.Database-class.html#GetPath qm.test.database.Database.SplitLabelLeft qm.test.database.Database-class.html#SplitLabelLeft qm.test.file_database.ExtensionDatabase.GetSuiteExtension qm.test.file_database.ExtensionDatabase-class.html#GetSuiteExtension qm.test.database.Database.TEST qm.test.database.Database-class.html#TEST qm.test.database.Database.IsModifiable qm.test.database.Database-class.html#IsModifiable qm.test.file_database.FileDatabase.GetIds qm.test.file_database.FileDatabase-class.html#GetIds qm.test.file_database.ExtensionDatabase._GetRelativeLabelPath qm.test.file_database.ExtensionDatabase-class.html#_GetRelativeLabelPath qm.test.database.Database.GetExtension qm.test.database.Database-class.html#GetExtension qm.test.file_database.FileDatabase._GetLabels qm.test.file_database.FileDatabase-class.html#_GetLabels qm.test.database.Database.RESOURCE qm.test.database.Database-class.html#RESOURCE qm.test.database.Database.HasSuite qm.test.database.Database-class.html#HasSuite qm.test.file_database.ExtensionDatabase._argument_dictionary qm.test.file_database.ExtensionDatabase-class.html#_argument_dictionary qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.database.Database.kind qm.test.database.Database-class.html#kind qm.test.file_database.ExtensionDatabase._GetPathFromLabel qm.test.file_database.ExtensionDatabase-class.html#_GetPathFromLabel qm.test.file_database.FileDatabase._GetResourceFromPath qm.test.file_database.FileDatabase-class.html#_GetResourceFromPath qm.test.database.Database.JoinLabels qm.test.database.Database-class.html#JoinLabels qm.test.database.Database._item_exceptions qm.test.database.Database-class.html#_item_exceptions qm.test.file_database.FileDatabase._GetTestFromPath qm.test.file_database.FileDatabase-class.html#_GetTestFromPath qm.test.database.Database._is_generic_database qm.test.database.Database-class.html#_is_generic_database qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.database.Database.GetItem qm.test.database.Database-class.html#GetItem qm.test.file_database.ExtensionDatabase._argument_list qm.test.file_database.ExtensionDatabase-class.html#_argument_list qm.test.database.Database.WriteExtension qm.test.database.Database-class.html#WriteExtension qm.test.file_database.ExtensionDatabase.GetTestPath qm.test.file_database.ExtensionDatabase-class.html#GetTestPath qm.test.file_database.ExtensionDatabase._IsSuiteFile qm.test.file_database.ExtensionDatabase-class.html#_IsSuiteFile qm.test.file_database.FileDatabase qm.test.file_database.FileDatabase-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.file_database.FileDatabase._GetLabelFromBasename qm.test.file_database.FileDatabase-class.html#_GetLabelFromBasename qm.test.file_database.FileDatabase.GetRoot qm.test.file_database.FileDatabase-class.html#GetRoot qm.test.database.Database.GetAttachmentStore qm.test.database.Database-class.html#GetAttachmentStore qm.test.file_database.FileDatabase._AreLabelsPaths qm.test.file_database.FileDatabase-class.html#_AreLabelsPaths qm.test.database.Database.GetTestClassNames qm.test.database.Database-class.html#GetTestClassNames qm.test.database.Database.modifiable qm.test.database.Database-class.html#modifiable qm.test.database.Database.GetResourceClassNames qm.test.database.Database-class.html#GetResourceClassNames qm.test.file_database.FileDatabase.GetTest qm.test.file_database.FileDatabase-class.html#GetTest qm.test.file_database.FileDatabase._GetPath qm.test.file_database.FileDatabase-class.html#_GetPath qm.test.file_database.FileDatabase.GetSuite qm.test.file_database.FileDatabase-class.html#GetSuite qm.test.file_database.FileDatabase.GetResourcePath qm.test.file_database.FileDatabase-class.html#GetResourcePath qm.test.database.Database.HasTest qm.test.database.Database-class.html#HasTest qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_database.FileDatabase.RemoveExtension qm.test.file_database.FileDatabase-class.html#RemoveExtension qm.test.database.Database.SUITE qm.test.database.Database-class.html#SUITE qm.test.database.Database.GetExtensions qm.test.database.Database-class.html#GetExtensions qm.test.database.Database.IsValidLabel qm.test.database.Database-class.html#IsValidLabel qm.test.file_database.FileDatabase._IsFile qm.test.file_database.FileDatabase-class.html#_IsFile qm.test.database.Database.GetResourceIds qm.test.database.Database-class.html#GetResourceIds qm.test.database.Database.RESOURCE qm.test.database.Database-class.html#RESOURCE qm.test.database.Database.WriteExtension qm.test.database.Database-class.html#WriteExtension qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.file_database.FileDatabase._GetSuiteFromPath qm.test.file_database.FileDatabase-class.html#_GetSuiteFromPath qm.test.database.Database.GetSuiteIds qm.test.database.Database-class.html#GetSuiteIds qm.test.file_database.FileDatabase.GetResource qm.test.file_database.FileDatabase-class.html#GetResource qm.test.database.Database.label_class qm.test.database.Database-class.html#label_class qm.test.database.Database.ITEM_KINDS qm.test.database.Database-class.html#ITEM_KINDS qm.test.database.Database.ExpandIds qm.test.database.Database-class.html#ExpandIds qm.test.database.Database.SplitLabel qm.test.database.Database-class.html#SplitLabel qm.test.file_database.FileDatabase.GetSubdirectories qm.test.file_database.FileDatabase-class.html#GetSubdirectories qm.test.database.Database.__init__ qm.test.database.Database-class.html#__init__ qm.test.database.Database.GetConfigurationDirectory qm.test.database.Database-class.html#GetConfigurationDirectory qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.database.Database.GetTestIds qm.test.database.Database-class.html#GetTestIds qm.test.database.Database.GetClassPaths qm.test.database.Database-class.html#GetClassPaths qm.test.database.Database.arguments qm.test.database.Database-class.html#arguments qm.test.file_database.FileDatabase.GetSuitePath qm.test.file_database.FileDatabase-class.html#GetSuitePath qm.test.file_database.FileDatabase._IsTestFile qm.test.file_database.FileDatabase-class.html#_IsTestFile qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.file_database.FileDatabase._IsResourceFile qm.test.file_database.FileDatabase-class.html#_IsResourceFile qm.test.database.Database.GetPath qm.test.database.Database-class.html#GetPath qm.test.database.Database.SplitLabelLeft qm.test.database.Database-class.html#SplitLabelLeft qm.test.file_database.FileDatabase._GetLabels qm.test.file_database.FileDatabase-class.html#_GetLabels qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.database.Database.IsModifiable qm.test.database.Database-class.html#IsModifiable qm.test.file_database.FileDatabase.GetIds qm.test.file_database.FileDatabase-class.html#GetIds qm.test.file_database.FileDatabase._GetRelativeLabelPath qm.test.file_database.FileDatabase-class.html#_GetRelativeLabelPath qm.test.database.Database.GetExtension qm.test.database.Database-class.html#GetExtension qm.test.database.Database.GetLabelComponents qm.test.database.Database-class.html#GetLabelComponents qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.database.Database.HasSuite qm.test.database.Database-class.html#HasSuite qm.test.database.Database._argument_dictionary qm.test.database.Database-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.database.Database.kind qm.test.database.Database-class.html#kind qm.test.file_database.FileDatabase._GetPathFromLabel qm.test.file_database.FileDatabase-class.html#_GetPathFromLabel qm.test.file_database.FileDatabase._GetResourceFromPath qm.test.file_database.FileDatabase-class.html#_GetResourceFromPath qm.test.database.Database.JoinLabels qm.test.database.Database-class.html#JoinLabels qm.test.database.Database._item_exceptions qm.test.database.Database-class.html#_item_exceptions qm.test.file_database.FileDatabase._GetTestFromPath qm.test.file_database.FileDatabase-class.html#_GetTestFromPath qm.test.database.Database._is_generic_database qm.test.database.Database-class.html#_is_generic_database qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.database.Database.GetItem qm.test.database.Database-class.html#GetItem qm.test.file_database.FileDatabase._argument_list qm.test.file_database.FileDatabase-class.html#_argument_list qm.test.database.Database.TEST qm.test.database.Database-class.html#TEST qm.test.database.Database.HasResource qm.test.database.Database-class.html#HasResource qm.test.file_database.FileDatabase.GetTestPath qm.test.file_database.FileDatabase-class.html#GetTestPath qm.test.file_database.FileDatabase._IsSuiteFile qm.test.file_database.FileDatabase-class.html#_IsSuiteFile qm.test.file_result_reader.FileResultReader qm.test.file_result_reader.FileResultReader-class.html qm.test.result_reader.ResultReader.GetAnnotations qm.test.result_reader.ResultReader-class.html#GetAnnotations qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.file_result_reader.FileResultReader.file qm.test.file_result_reader.FileResultReader-class.html#file qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.file_result_reader.FileResultReader.__init__ qm.test.file_result_reader.FileResultReader-class.html#__init__ qm.test.file_result_reader.FileResultReader._argument_dictionary qm.test.file_result_reader.FileResultReader-class.html#_argument_dictionary qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.file_result_reader.FileResultReader.InvalidFile qm.test.file_result_reader.FileResultReader.InvalidFile-class.html qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_reader.FileResultReader.filename qm.test.file_result_reader.FileResultReader-class.html#filename qm.test.file_result_reader.FileResultReader.arguments qm.test.file_result_reader.FileResultReader-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_reader.ResultReader.GetResult qm.test.result_reader.ResultReader-class.html#GetResult qm.test.result_reader.ResultReader.__iter__ qm.test.result_reader.ResultReader-class.html#__iter__ qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_reader.FileResultReader._is_binary_file qm.test.file_result_reader.FileResultReader-class.html#_is_binary_file qm.test.result_reader.ResultReader.kind qm.test.result_reader.ResultReader-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.file_result_reader.FileResultReader._argument_list qm.test.file_result_reader.FileResultReader-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.file_result_reader.FileResultReader.InvalidFile qm.test.file_result_reader.FileResultReader.InvalidFile-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.test.file_result_stream.FileResultStream qm.test.file_result_stream.FileResultStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.file_result_stream.FileResultStream.file qm.test.file_result_stream.FileResultStream-class.html#file qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.file_result_stream.FileResultStream.__init__ qm.test.file_result_stream.FileResultStream-class.html#__init__ qm.test.file_result_stream.FileResultStream._argument_dictionary qm.test.file_result_stream.FileResultStream-class.html#_argument_dictionary qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.result_stream.ResultStream.WriteResult qm.test.result_stream.ResultStream-class.html#WriteResult qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.file_result_stream.FileResultStream.filename qm.test.file_result_stream.FileResultStream-class.html#filename qm.test.file_result_stream.FileResultStream.arguments qm.test.file_result_stream.FileResultStream-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.result_stream.ResultStream.Summarize qm.test.result_stream.ResultStream-class.html#Summarize qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.file_result_stream.FileResultStream._is_binary_file qm.test.file_result_stream.FileResultStream-class.html#_is_binary_file qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.file_result_stream.FileResultStream._argument_list qm.test.file_result_stream.FileResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.result_stream.ResultStream.WriteAnnotation qm.test.result_stream.ResultStream-class.html#WriteAnnotation qm.test.parameter_database.ParameterDatabase qm.test.parameter_database.ParameterDatabase-class.html qm.test.parameter_database.ParameterDatabase.GetAttachmentStore qm.test.parameter_database.ParameterDatabase-class.html#GetAttachmentStore qm.test.parameter_database.ParameterDatabase.ImplicitSuite qm.test.parameter_database.ParameterDatabase.ImplicitSuite-class.html qm.test.database.Database.modifiable qm.test.database.Database-class.html#modifiable qm.test.parameter_database.ParameterDatabase.GetClassPath qm.test.parameter_database.ParameterDatabase-class.html#GetClassPath qm.test.parameter_database.ParameterDatabase.GetTest qm.test.parameter_database.ParameterDatabase-class.html#GetTest qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.database.Database.RemoveExtension qm.test.database.Database-class.html#RemoveExtension qm.test.parameter_database.ParameterDatabase.HasTest qm.test.parameter_database.ParameterDatabase-class.html#HasTest qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.parameter_database.ParameterDatabase.GetSuite qm.test.parameter_database.ParameterDatabase-class.html#GetSuite qm.test.database.Database.SUITE qm.test.database.Database-class.html#SUITE qm.test.database.Database.GetExtensions qm.test.database.Database-class.html#GetExtensions qm.test.database.Database.IsValidLabel qm.test.database.Database-class.html#IsValidLabel qm.test.parameter_database.ParameterDatabase.__init__ qm.test.parameter_database.ParameterDatabase-class.html#__init__ qm.test.parameter_database.ParameterDatabase.GetResourceIds qm.test.parameter_database.ParameterDatabase-class.html#GetResourceIds qm.test.database.Database.RESOURCE qm.test.database.Database-class.html#RESOURCE qm.test.parameter_database.ParameterDatabase.ParameterSuite qm.test.parameter_database.ParameterDatabase.ParameterSuite-class.html qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.database.Database.JoinLabels qm.test.database.Database-class.html#JoinLabels qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.parameter_database.ParameterDatabase.GetResource qm.test.parameter_database.ParameterDatabase-class.html#GetResource qm.test.database.Database.label_class qm.test.database.Database-class.html#label_class qm.test.parameter_database.ParameterDatabase.GetWrappedDatabase qm.test.parameter_database.ParameterDatabase-class.html#GetWrappedDatabase qm.test.database.Database.ExpandIds qm.test.database.Database-class.html#ExpandIds qm.test.database.Database.SplitLabel qm.test.database.Database-class.html#SplitLabel qm.test.parameter_database.ParameterDatabase.GetSubdirectories qm.test.parameter_database.ParameterDatabase-class.html#GetSubdirectories qm.test.database.Database._is_generic_database qm.test.database.Database-class.html#_is_generic_database qm.test.database.Database.arguments qm.test.database.Database-class.html#arguments qm.test.database.Database.GetConfigurationDirectory qm.test.database.Database-class.html#GetConfigurationDirectory qm.test.parameter_database.ParameterDatabase.GetTestIds qm.test.parameter_database.ParameterDatabase-class.html#GetTestIds qm.test.database.Database.GetClassPaths qm.test.database.Database-class.html#GetClassPaths qm.test.parameter_database.ParameterDatabase.HasResource qm.test.parameter_database.ParameterDatabase-class.html#HasResource qm.test.parameter_database.ParameterDatabase.GetTestClassNames qm.test.parameter_database.ParameterDatabase-class.html#GetTestClassNames qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.database.Database.WriteExtension qm.test.database.Database-class.html#WriteExtension qm.test.database.Database.SplitLabelLeft qm.test.database.Database-class.html#SplitLabelLeft qm.test.database.Database.GetPath qm.test.database.Database-class.html#GetPath qm.test.parameter_database.ParameterDatabase.GetResourceClassNames qm.test.parameter_database.ParameterDatabase-class.html#GetResourceClassNames qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.database.Database.IsModifiable qm.test.database.Database-class.html#IsModifiable qm.test.parameter_database.ParameterDatabase.WrapperSuite qm.test.parameter_database.ParameterDatabase.WrapperSuite-class.html qm.test.parameter_database.ParameterDatabase._GetArgumentsForParameter qm.test.parameter_database.ParameterDatabase-class.html#_GetArgumentsForParameter qm.test.parameter_database.ParameterDatabase.GetSuiteIds qm.test.parameter_database.ParameterDatabase-class.html#GetSuiteIds qm.test.database.Database.GetExtension qm.test.database.Database-class.html#GetExtension qm.test.database.Database.GetLabelComponents qm.test.database.Database-class.html#GetLabelComponents qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.parameter_database.ParameterDatabase.HasSuite qm.test.parameter_database.ParameterDatabase-class.html#HasSuite qm.test.database.Database._argument_dictionary qm.test.database.Database-class.html#_argument_dictionary qm.test.database.Database.kind qm.test.database.Database-class.html#kind qm.test.database.Database.ITEM_KINDS qm.test.database.Database-class.html#ITEM_KINDS qm.test.database.Database._item_exceptions qm.test.database.Database-class.html#_item_exceptions qm.test.parameter_database.ParameterDatabase._GetParametersForTest qm.test.parameter_database.ParameterDatabase-class.html#_GetParametersForTest qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.database.Database.GetItem qm.test.database.Database-class.html#GetItem qm.test.parameter_database.ParameterDatabase._argument_list qm.test.parameter_database.ParameterDatabase-class.html#_argument_list qm.test.database.Database.TEST qm.test.database.Database-class.html#TEST qm.test.parameter_database.ParameterDatabase.GetIds qm.test.parameter_database.ParameterDatabase-class.html#GetIds qm.test.parameter_database.ParameterDatabase.ImplicitSuite qm.test.parameter_database.ParameterDatabase.ImplicitSuite-class.html qm.test.suite.Suite.GetAllTestAndSuiteIds qm.test.suite.Suite-class.html#GetAllTestAndSuiteIds qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.parameter_database.ParameterDatabase.ImplicitSuite.__init__ qm.test.parameter_database.ParameterDatabase.ImplicitSuite-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.parameter_database.ParameterDatabase.ImplicitSuite.IsImplicit qm.test.parameter_database.ParameterDatabase.ImplicitSuite-class.html#IsImplicit qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.suite.Suite.arguments qm.test.suite.Suite-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.parameter_database.ParameterDatabase.ImplicitSuite.GetTestIds qm.test.parameter_database.ParameterDatabase.ImplicitSuite-class.html#GetTestIds qm.test.suite.Suite.GetDatabase qm.test.suite.Suite-class.html#GetDatabase qm.test.suite.Suite.GetId qm.test.suite.Suite-class.html#GetId qm.test.suite.Suite.GetSuiteIds qm.test.suite.Suite-class.html#GetSuiteIds qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.suite.Suite.kind qm.test.suite.Suite-class.html#kind qm.test.suite.Suite.EXTRA_DATABASE qm.test.suite.Suite-class.html#EXTRA_DATABASE qm.test.suite.Suite.EXTRA_ID qm.test.suite.Suite-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.parameter_database.ParameterDatabase.ParameterSuite qm.test.parameter_database.ParameterDatabase.ParameterSuite-class.html qm.test.suite.Suite.GetAllTestAndSuiteIds qm.test.suite.Suite-class.html#GetAllTestAndSuiteIds qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.parameter_database.ParameterDatabase.ParameterSuite.__init__ qm.test.parameter_database.ParameterDatabase.ParameterSuite-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.parameter_database.ParameterDatabase.ParameterSuite.IsImplicit qm.test.parameter_database.ParameterDatabase.ParameterSuite-class.html#IsImplicit qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.suite.Suite.arguments qm.test.suite.Suite-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.parameter_database.ParameterDatabase.ParameterSuite.GetTestIds qm.test.parameter_database.ParameterDatabase.ParameterSuite-class.html#GetTestIds qm.test.suite.Suite.GetDatabase qm.test.suite.Suite-class.html#GetDatabase qm.test.suite.Suite.GetId qm.test.suite.Suite-class.html#GetId qm.test.parameter_database.ParameterDatabase.ParameterSuite.GetSuiteIds qm.test.parameter_database.ParameterDatabase.ParameterSuite-class.html#GetSuiteIds qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.suite.Suite.kind qm.test.suite.Suite-class.html#kind qm.test.suite.Suite.EXTRA_DATABASE qm.test.suite.Suite-class.html#EXTRA_DATABASE qm.test.suite.Suite.EXTRA_ID qm.test.suite.Suite-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.parameter_database.ParameterDatabase.WrapperSuite qm.test.parameter_database.ParameterDatabase.WrapperSuite-class.html qm.test.parameter_database.ParameterDatabase.WrapperSuite.GetAllTestAndSuiteIds qm.test.parameter_database.ParameterDatabase.WrapperSuite-class.html#GetAllTestAndSuiteIds qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.parameter_database.ParameterDatabase.WrapperSuite.__init__ qm.test.parameter_database.ParameterDatabase.WrapperSuite-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.parameter_database.ParameterDatabase.WrapperSuite.IsImplicit qm.test.parameter_database.ParameterDatabase.WrapperSuite-class.html#IsImplicit qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.suite.Suite.arguments qm.test.suite.Suite-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.parameter_database.ParameterDatabase.WrapperSuite.GetTestIds qm.test.parameter_database.ParameterDatabase.WrapperSuite-class.html#GetTestIds qm.test.suite.Suite.GetDatabase qm.test.suite.Suite-class.html#GetDatabase qm.test.suite.Suite.GetId qm.test.suite.Suite-class.html#GetId qm.test.parameter_database.ParameterDatabase.WrapperSuite.GetSuiteIds qm.test.parameter_database.ParameterDatabase.WrapperSuite-class.html#GetSuiteIds qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.suite.Suite.kind qm.test.suite.Suite-class.html#kind qm.test.suite.Suite.EXTRA_DATABASE qm.test.suite.Suite-class.html#EXTRA_DATABASE qm.test.suite.Suite.EXTRA_ID qm.test.suite.Suite-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.reader_test_run.ReaderTestRun qm.test.reader_test_run.ReaderTestRun-class.html qm.test.reader_test_run.ReaderTestRun.GetAllResults qm.test.reader_test_run.ReaderTestRun-class.html#GetAllResults qm.test.reader_test_run.ReaderTestRun.GetAnnotations qm.test.reader_test_run.ReaderTestRun-class.html#GetAnnotations qm.test.test_run.TestRun.CountOutcomes qm.test.test_run.TestRun-class.html#CountOutcomes qm.test.reader_test_run.ReaderTestRun.GetResult qm.test.reader_test_run.ReaderTestRun-class.html#GetResult qm.test.test_run.TestRun.GetResultsByOutcome qm.test.test_run.TestRun-class.html#GetResultsByOutcome qm.test.reader_test_run.ReaderTestRun.GetAnnotation qm.test.reader_test_run.ReaderTestRun-class.html#GetAnnotation qm.test.reader_test_run.ReaderTestRun.__init__ qm.test.reader_test_run.ReaderTestRun-class.html#__init__ qm.test.report.ReportGenerator qm.test.report.ReportGenerator-class.html qm.test.report.ReportGenerator.GenerateReport qm.test.report.ReportGenerator-class.html#GenerateReport qm.test.report.ReportGenerator._GetIds qm.test.report.ReportGenerator-class.html#_GetIds qm.test.report.ReportGenerator._ReportItem qm.test.report.ReportGenerator-class.html#_ReportItem qm.test.report.ReportGenerator._LoadTestRuns qm.test.report.ReportGenerator-class.html#_LoadTestRuns qm.test.report.ReportGenerator._ReportSubdirectory qm.test.report.ReportGenerator-class.html#_ReportSubdirectory qm.test.report.ReportGenerator._Report qm.test.report.ReportGenerator-class.html#_Report qm.test.report.ReportGenerator._ReportFlat qm.test.report.ReportGenerator-class.html#_ReportFlat qm.test.report.ReportGenerator.__init__ qm.test.report.ReportGenerator-class.html#__init__ qm.test.resource.Resource qm.test.resource.Resource-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.resource.Resource.CleanUp qm.test.resource.Resource-class.html#CleanUp qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.arguments qm.test.runnable.Runnable-class.html#arguments qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.resource.Resource.kind qm.test.resource.Resource-class.html#kind qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.resource.Resource.SetUp qm.test.resource.Resource-class.html#SetUp qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.test.resource_adapter.ResourceAdapter qm.test.resource_adapter.ResourceAdapter-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.resource.Resource.CleanUp qm.test.resource.Resource-class.html#CleanUp qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.arguments qm.test.runnable.Runnable-class.html#arguments qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.test.resource.Resource.kind qm.test.resource.Resource-class.html#kind qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.resource_adapter.ResourceAdapter.SetUp qm.test.resource_adapter.ResourceAdapter-class.html#SetUp qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.test.result.Result qm.test.result.Result-class.html qm.test.result.Result.EXCEPTION qm.test.result.Result-class.html#EXCEPTION qm.test.result.Result.PASS qm.test.result.Result-class.html#PASS qm.test.result.Result.GetKind qm.test.result.Result-class.html#GetKind qm.test.result.Result.outcomes qm.test.result.Result-class.html#outcomes qm.test.result.Result.FAIL qm.test.result.Result-class.html#FAIL qm.test.result.Result.NoteException qm.test.result.Result-class.html#NoteException qm.test.result.Result.has_key qm.test.result.Result-class.html#has_key qm.test.result.Result.UNTESTED qm.test.result.Result-class.html#UNTESTED qm.test.result.Result.__init__ qm.test.result.Result-class.html#__init__ qm.test.result.Result.RESOURCE qm.test.result.Result-class.html#RESOURCE qm.test.result.Result.Quote qm.test.result.Result-class.html#Quote qm.test.result.Result.START_TIME qm.test.result.Result-class.html#START_TIME qm.test.result.Result.__setstate__ qm.test.result.Result-class.html#__setstate__ qm.test.result.Result.SetCause qm.test.result.Result-class.html#SetCause qm.test.result.Result.GetOutcome qm.test.result.Result-class.html#GetOutcome qm.test.result.Result.__getstate__ qm.test.result.Result-class.html#__getstate__ qm.test.result.Result.RESOURCE_CLEANUP qm.test.result.Result-class.html#RESOURCE_CLEANUP qm.test.result.Result.CheckExitStatus qm.test.result.Result-class.html#CheckExitStatus qm.test.result.Result.kinds qm.test.result.Result-class.html#kinds qm.test.result.Result.__getitem__ qm.test.result.Result-class.html#__getitem__ qm.test.result.Result.get qm.test.result.Result-class.html#get qm.test.result.Result.keys qm.test.result.Result-class.html#keys qm.test.result.Result.TRACEBACK qm.test.result.Result-class.html#TRACEBACK qm.test.result.Result.GetCause qm.test.result.Result-class.html#GetCause qm.test.result.Result.GetId qm.test.result.Result-class.html#GetId qm.test.result.Result.TEST qm.test.result.Result-class.html#TEST qm.test.result.Result.__setitem__ qm.test.result.Result-class.html#__setitem__ qm.test.result.Result.END_TIME qm.test.result.Result-class.html#END_TIME qm.test.result.Result.ERROR qm.test.result.Result-class.html#ERROR qm.test.result.Result.RESOURCE_SETUP qm.test.result.Result-class.html#RESOURCE_SETUP qm.test.result.Result.CAUSE qm.test.result.Result-class.html#CAUSE qm.test.result.Result.__delitem__ qm.test.result.Result-class.html#__delitem__ qm.test.result.Result.TARGET qm.test.result.Result-class.html#TARGET qm.test.result.Result.items qm.test.result.Result-class.html#items qm.test.result.Result.MakeDomNode qm.test.result.Result-class.html#MakeDomNode qm.test.result.Result.Annotate qm.test.result.Result-class.html#Annotate qm.test.result.Result.SetOutcome qm.test.result.Result-class.html#SetOutcome qm.test.result.Result.Fail qm.test.result.Result-class.html#Fail qm.test.result_reader.ResultReader qm.test.result_reader.ResultReader-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.result_reader.ResultReader.GetAnnotations qm.test.result_reader.ResultReader-class.html#GetAnnotations qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.result_reader.ResultReader.__init__ qm.test.result_reader.ResultReader-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_reader.ResultReader.GetResult qm.test.result_reader.ResultReader-class.html#GetResult qm.test.result_reader.ResultReader.__iter__ qm.test.result_reader.ResultReader-class.html#__iter__ qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.result_reader.ResultReader.kind qm.test.result_reader.ResultReader-class.html#kind qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.result_stream.ResultStream qm.test.result_stream.ResultStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.result_stream.ResultStream.__init__ qm.test.result_stream.ResultStream-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.result_stream.ResultStream.WriteResult qm.test.result_stream.ResultStream-class.html#WriteResult qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.result_stream.ResultStream.Summarize qm.test.result_stream.ResultStream-class.html#Summarize qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.result_stream.ResultStream._argument_dictionary qm.test.result_stream.ResultStream-class.html#_argument_dictionary qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.result_stream.ResultStream._argument_list qm.test.result_stream.ResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.result_stream.ResultStream.WriteAnnotation qm.test.result_stream.ResultStream-class.html#WriteAnnotation qm.test.run_database.RunDatabase qm.test.run_database.RunDatabase-class.html qm.test.run_database.RunDatabase.GetAnnotations qm.test.run_database.RunDatabase-class.html#GetAnnotations qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.run_database.RunDatabase.GetRunInTimeframe qm.test.run_database.RunDatabase-class.html#GetRunInTimeframe qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.extension.Extension.__init__ qm.extension.Extension-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.run_database.RunDatabase.GetAllRuns qm.test.run_database.RunDatabase-class.html#GetAllRuns qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.run_database.RunDatabase.GetOutcomes qm.test.run_database.RunDatabase-class.html#GetOutcomes qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.kind qm.extension.Extension-class.html#kind qm.test.run_database.RunDatabase.GetTimeframe qm.test.run_database.RunDatabase-class.html#GetTimeframe qm.test.run_database.RunDatabase.GetRuns qm.test.run_database.RunDatabase-class.html#GetRuns qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.run_database.RunDatabase.GetRunsByAnnotations qm.test.run_database.RunDatabase-class.html#GetRunsByAnnotations qm.test.runnable.Runnable qm.test.runnable.Runnable-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__GetAttachments qm.test.runnable.Runnable-class.html#__GetAttachments qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.arguments qm.test.runnable.Runnable-class.html#arguments qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable._argument_dictionary qm.test.runnable.Runnable-class.html#_argument_dictionary qm.extension.Extension.kind qm.extension.Extension-class.html#kind qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.runnable.Runnable._argument_list qm.test.runnable.Runnable-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.TextField.GetHelp qm.fields.TextField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.TextField.__init__ qm.fields.TextField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.TextField.MakeDomNodeForValue qm.fields.TextField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.ChoiceField.FormatValueAsHtml qm.fields.ChoiceField-class.html#FormatValueAsHtml qm.fields.ChoiceField.Validate qm.fields.ChoiceField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.TextField.GetValueFromDomNode qm.fields.TextField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.test.runnable.Runnable.ResourceField.GetItems qm.test.runnable.Runnable.ResourceField-class.html#GetItems qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.test.suite.Suite qm.test.suite.Suite-class.html qm.test.suite.Suite.GetAllTestAndSuiteIds qm.test.suite.Suite-class.html#GetAllTestAndSuiteIds qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.suite.Suite.__init__ qm.test.suite.Suite-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.suite.Suite.IsImplicit qm.test.suite.Suite-class.html#IsImplicit qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.suite.Suite.arguments qm.test.suite.Suite-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.suite.Suite.GetTestIds qm.test.suite.Suite-class.html#GetTestIds qm.test.suite.Suite.GetDatabase qm.test.suite.Suite-class.html#GetDatabase qm.test.suite.Suite.GetId qm.test.suite.Suite-class.html#GetId qm.test.suite.Suite.GetSuiteIds qm.test.suite.Suite-class.html#GetSuiteIds qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.test.suite.Suite.kind qm.test.suite.Suite-class.html#kind qm.test.suite.Suite.EXTRA_DATABASE qm.test.suite.Suite-class.html#EXTRA_DATABASE qm.test.suite.Suite.EXTRA_ID qm.test.suite.Suite-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.target.Target qm.test.target.Target-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.test.target.Target.RunTest qm.test.target.Target-class.html#RunTest qm.test.target.Target.Start qm.test.target.Target-class.html#Start qm.test.target.Target._BeginResourceSetUp qm.test.target.Target-class.html#_BeginResourceSetUp qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.target.Target.__init__ qm.test.target.Target-class.html#__init__ qm.test.target.Target._RecordResult qm.test.target.Target-class.html#_RecordResult qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.target.Target.Stop qm.test.target.Target-class.html#Stop qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.target.Target.__ResourceSetUpException qm.test.target.Target.__ResourceSetUpException-class.html qm.test.target.Target.arguments qm.test.target.Target-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.target.Target.__SetUpResources qm.test.target.Target-class.html#__SetUpResources qm.test.target.Target.GetGroup qm.test.target.Target-class.html#GetGroup qm.test.target.Target.GetDatabase qm.test.target.Target-class.html#GetDatabase qm.test.target.Target._GetTemporaryDirectory qm.test.target.Target-class.html#_GetTemporaryDirectory qm.test.target.Target.GetName qm.test.target.Target-class.html#GetName qm.test.target.Target._FinishResourceSetUp qm.test.target.Target-class.html#_FinishResourceSetUp qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.target.Target._SetUpResource qm.test.target.Target-class.html#_SetUpResource qm.extension.Extension._argument_dictionary qm.extension.Extension-class.html#_argument_dictionary qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.target.Target.kind qm.test.target.Target-class.html#kind qm.test.target.Target._CleanUpResource qm.test.target.Target-class.html#_CleanUpResource qm.test.target.Target.IsInGroup qm.test.target.Target-class.html#IsInGroup qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.extension.Extension._argument_list qm.extension.Extension-class.html#_argument_list qm.test.target.Target.IsIdle qm.test.target.Target-class.html#IsIdle qm.test.target.Target.__ResourceSetUpException qm.test.target.Target.__ResourceSetUpException-class.html qm.test.target.Target.__ResourceSetUpException.__init__ qm.test.target.Target.__ResourceSetUpException-class.html#__init__ qm.test.test.TargetGroupField qm.test.test.TargetGroupField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.TextField.GetHelp qm.fields.TextField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.TextField.__init__ qm.fields.TextField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.TextField.MakeDomNodeForValue qm.fields.TextField-class.html#MakeDomNodeForValue qm.test.test.TargetGroupField.GetDescription qm.test.test.TargetGroupField-class.html#GetDescription qm.fields.TextField.FormatValueAsHtml qm.fields.TextField-class.html#FormatValueAsHtml qm.fields.TextField.Validate qm.fields.TextField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.TextField.GetValueFromDomNode qm.fields.TextField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.test.test.Test qm.test.test.Test-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.runnable.Runnable.GetAttachments qm.test.runnable.Runnable-class.html#GetAttachments qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.runnable.Runnable.RESOURCE_FIELD_ID qm.test.runnable.Runnable-class.html#RESOURCE_FIELD_ID qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.runnable.Runnable.__init__ qm.test.runnable.Runnable-class.html#__init__ qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.test.test.Test.Run qm.test.test.Test-class.html#Run qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.test.test.Test.arguments qm.test.test.Test-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.runnable.Runnable.resources qm.test.runnable.Runnable-class.html#resources qm.test.runnable.Runnable.ResourceField qm.test.runnable.Runnable.ResourceField-class.html qm.test.runnable.Runnable.GetDatabase qm.test.runnable.Runnable-class.html#GetDatabase qm.test.test.Test.PREREQUISITES_FIELD_ID qm.test.test.Test-class.html#PREREQUISITES_FIELD_ID qm.test.test.Test.GetTargetGroup qm.test.test.Test-class.html#GetTargetGroup qm.test.test.Test.target_group qm.test.test.Test-class.html#target_group qm.test.runnable.Runnable.GetId qm.test.runnable.Runnable-class.html#GetId qm.test.runnable.Runnable.EXTRA_DATABASE qm.test.runnable.Runnable-class.html#EXTRA_DATABASE qm.test.test.Test._argument_dictionary qm.test.test.Test-class.html#_argument_dictionary qm.test.test.Test.kind qm.test.test.Test-class.html#kind qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.test.test.Test.prerequisites qm.test.test.Test-class.html#prerequisites qm.test.runnable.Runnable.EXTRA_ID qm.test.runnable.Runnable-class.html#EXTRA_ID qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.test.Test._argument_list qm.test.test.Test-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.EnumerationField.GetHelp qm.fields.EnumerationField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.test.test.Test.OutcomeField.__init__ qm.test.test.Test.OutcomeField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.EnumerationField.MakeDomNodeForValue qm.fields.EnumerationField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.ChoiceField.FormatValueAsHtml qm.fields.ChoiceField-class.html#FormatValueAsHtml qm.fields.ChoiceField.Validate qm.fields.ChoiceField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.EnumerationField.GetValueFromDomNode qm.fields.EnumerationField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.EnumerationField.GetItems qm.fields.EnumerationField-class.html#GetItems qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.test.test.Test.OutcomeField qm.test.test.Test.OutcomeField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.EnumerationField.GetHelp qm.fields.EnumerationField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.test.test.Test.OutcomeField.__init__ qm.test.test.Test.OutcomeField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.EnumerationField.MakeDomNodeForValue qm.fields.EnumerationField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.ChoiceField.FormatValueAsHtml qm.fields.ChoiceField-class.html#FormatValueAsHtml qm.fields.ChoiceField.Validate qm.fields.ChoiceField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.EnumerationField.GetValueFromDomNode qm.fields.EnumerationField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.fields.EnumerationField.GetItems qm.fields.EnumerationField-class.html#GetItems qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.TextField.GetHelp qm.fields.TextField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.TextField.__init__ qm.fields.TextField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.TextField.MakeDomNodeForValue qm.fields.TextField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.ChoiceField.FormatValueAsHtml qm.fields.ChoiceField-class.html#FormatValueAsHtml qm.fields.ChoiceField.Validate qm.fields.ChoiceField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.TextField.GetValueFromDomNode qm.fields.TextField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.test.test.Test.TestField.GetItems qm.test.test.Test.TestField-class.html#GetItems qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.test.test.Test.TestField qm.test.test.Test.TestField-class.html qm.fields.TextField.ParseFormValue qm.fields.TextField-class.html#ParseFormValue qm.fields.Field.IsReadOnly qm.fields.Field-class.html#IsReadOnly qm.fields.TextField.FormatValueAsText qm.fields.TextField-class.html#FormatValueAsText qm.fields.TextField.GetHelp qm.fields.TextField-class.html#GetHelp qm.fields.Field.GetSubfields qm.fields.Field-class.html#GetSubfields qm.fields.Field.form_field_prefix qm.fields.Field-class.html#form_field_prefix qm.fields.TextField.__init__ qm.fields.TextField-class.html#__init__ qm.fields.Field.GetDefaultValue qm.fields.Field-class.html#GetDefaultValue qm.fields.TextField.MakeDomNodeForValue qm.fields.TextField-class.html#MakeDomNodeForValue qm.fields.Field.GetDescription qm.fields.Field-class.html#GetDescription qm.fields.ChoiceField.FormatValueAsHtml qm.fields.ChoiceField-class.html#FormatValueAsHtml qm.fields.ChoiceField.Validate qm.fields.ChoiceField-class.html#Validate qm.fields.Field.GetBriefDescription qm.fields.Field-class.html#GetBriefDescription qm.fields.Field.GetName qm.fields.Field-class.html#GetName qm.fields.Field.GetHtmlFormFieldName qm.fields.Field-class.html#GetHtmlFormFieldName qm.fields.TextField.GetValueFromDomNode qm.fields.TextField-class.html#GetValueFromDomNode qm.fields.Field.IsHidden qm.fields.Field-class.html#IsHidden qm.fields.Field.GetHtmlHelp qm.fields.Field-class.html#GetHtmlHelp qm.fields.Field.SetName qm.fields.Field-class.html#SetName qm.test.test.Test.TestField.GetItems qm.test.test.Test.TestField-class.html#GetItems qm.fields.Field.__repr__ qm.fields.Field-class.html#__repr__ qm.fields.Field.GetTitle qm.fields.Field-class.html#GetTitle qm.fields.TextField.ParseTextValue qm.fields.TextField-class.html#ParseTextValue qm.fields.Field.IsComputed qm.fields.Field-class.html#IsComputed qm.test.test_run.TestRun qm.test.test_run.TestRun-class.html qm.test.test_run.TestRun.GetAllResults qm.test.test_run.TestRun-class.html#GetAllResults qm.test.test_run.TestRun.GetAnnotations qm.test.test_run.TestRun-class.html#GetAnnotations qm.test.test_run.TestRun.CountOutcomes qm.test.test_run.TestRun-class.html#CountOutcomes qm.test.test_run.TestRun.GetResult qm.test.test_run.TestRun-class.html#GetResult qm.test.test_run.TestRun.GetResultsByOutcome qm.test.test_run.TestRun-class.html#GetResultsByOutcome qm.test.test_run.TestRun.GetAnnotation qm.test.test_run.TestRun-class.html#GetAnnotation qm.test.web.web.ContextPage qm.test.web.web.ContextPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.ContextPage.__init__ qm.test.web.web.ContextPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage qm.test.web.web.DefaultDtmlPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.web.DtmlPage.GenerateHtmlHeader qm.web.DtmlPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.DefaultDtmlPage.__init__ qm.test.web.web.DefaultDtmlPage-class.html#__init__ qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.web.DtmlPage.GenerateStartBody qm.web.DtmlPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.DirPage qm.test.web.web.DirPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.test.web.web.DirPage.GetRefreshDelay qm.test.web.web.DirPage-class.html#GetRefreshDelay qm.test.web.web.DirPage.__init__ qm.test.web.web.DirPage-class.html#__init__ qm.test.web.web.DirPage.CountUnexpected qm.test.web.web.DirPage-class.html#CountUnexpected qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.test.web.web.DirPage.GetUnexpectedResultsByOutcome qm.test.web.web.DirPage-class.html#GetUnexpectedResultsByOutcome qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DirPage.GetSortURL qm.test.web.web.DirPage-class.html#GetSortURL qm.test.web.web.DirPage.GetTestResultsForDirectory qm.test.web.web.DirPage-class.html#GetTestResultsForDirectory qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.test.web.web.DirPage.SORT_KINDS qm.test.web.web.DirPage-class.html#SORT_KINDS qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.test.web.web.DirPage.SORT_EXPECTATION qm.test.web.web.DirPage-class.html#SORT_EXPECTATION qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DirPage.GetRunUrl qm.test.web.web.DirPage-class.html#GetRunUrl qm.test.web.web.DirPage.SORT_OUTCOME qm.test.web.web.DirPage-class.html#SORT_OUTCOME qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.DirPage.GetTests qm.test.web.web.DirPage-class.html#GetTests qm.test.web.web.DirPage.IsFinished qm.test.web.web.DirPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.DirPage.GetExpectation qm.test.web.web.DirPage-class.html#GetExpectation qm.test.web.web.DirPage.SORT_NAME qm.test.web.web.DirPage-class.html#SORT_NAME qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.DirPage.GetResultURL qm.test.web.web.DirPage-class.html#GetResultURL qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.DirPage.GetUnexpectedOutcomePercentages qm.test.web.web.DirPage-class.html#GetUnexpectedOutcomePercentages qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.DirPage.GetTestOutcome qm.test.web.web.DirPage-class.html#GetTestOutcome qm.test.web.web.DirPage.GetDetailURL qm.test.web.web.DirPage-class.html#GetDetailURL qm.test.web.web.DirReportPage qm.test.web.web.DirReportPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DirReportPage.MakeTestRunUrl qm.test.web.web.DirReportPage-class.html#MakeTestRunUrl qm.test.web.web.QMTestReportPage.GenerateHtmlHeader qm.test.web.web.QMTestReportPage-class.html#GenerateHtmlHeader qm.test.web.web.DirReportPage.SORT_KINDS qm.test.web.web.DirReportPage-class.html#SORT_KINDS qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.DirReportPage.__init__ qm.test.web.web.DirReportPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.QMTestReportPage.GetRunDatabase qm.test.web.web.QMTestReportPage-class.html#GetRunDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.test.web.web.DirReportPage.SORT_EXPECTATION qm.test.web.web.DirReportPage-class.html#SORT_EXPECTATION qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestReportPage.GenerateStartBody qm.test.web.web.QMTestReportPage-class.html#GenerateStartBody qm.test.web.web.DirReportPage.SORT_OUTCOME qm.test.web.web.DirReportPage-class.html#SORT_OUTCOME qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.test.web.web.QMTestReportPage.FormatTimeIso qm.test.web.web.QMTestReportPage-class.html#FormatTimeIso qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.DirReportPage.GetItems qm.test.web.web.DirReportPage-class.html#GetItems qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.DirReportPage.SORT_NAME qm.test.web.web.DirReportPage-class.html#SORT_NAME qm.test.web.web.QMTestReportPage.GetResultURL qm.test.web.web.QMTestReportPage-class.html#GetResultURL qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.Item qm.test.web.web.Item-class.html qm.test.web.web.Item.__init__ qm.test.web.web.Item-class.html#__init__ qm.test.web.web.LoadContextPage qm.test.web.web.LoadContextPage-class.html qm.test.web.web.LoadContextPage.prompt qm.test.web.web.LoadContextPage-class.html#prompt qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.test.web.web.LoadContextPage.title qm.test.web.web.LoadContextPage-class.html#title qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.LoadContextPage.__init__ qm.test.web.web.LoadContextPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.LoadContextPage.submit_url qm.test.web.web.LoadContextPage-class.html#submit_url qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.LoadContextPage.heading qm.test.web.web.LoadContextPage-class.html#heading qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.LoadExpectationsPage qm.test.web.web.LoadExpectationsPage-class.html qm.test.web.web.LoadExpectationsPage.prompt qm.test.web.web.LoadExpectationsPage-class.html#prompt qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.test.web.web.LoadExpectationsPage.title qm.test.web.web.LoadExpectationsPage-class.html#title qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.LoadExpectationsPage.__init__ qm.test.web.web.LoadExpectationsPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.LoadExpectationsPage.submit_url qm.test.web.web.LoadExpectationsPage-class.html#submit_url qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.LoadExpectationsPage.heading qm.test.web.web.LoadExpectationsPage-class.html#heading qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.LoadResultsPage qm.test.web.web.LoadResultsPage-class.html qm.test.web.web.LoadResultsPage.prompt qm.test.web.web.LoadResultsPage-class.html#prompt qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.test.web.web.LoadResultsPage.title qm.test.web.web.LoadResultsPage-class.html#title qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.LoadResultsPage.__init__ qm.test.web.web.LoadResultsPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.LoadResultsPage.submit_url qm.test.web.web.LoadResultsPage-class.html#submit_url qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.LoadResultsPage.heading qm.test.web.web.LoadResultsPage-class.html#heading qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.NewItemPage qm.test.web.web.NewItemPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.test.web.web.NewItemPage.MakeSubmitUrl qm.test.web.web.NewItemPage-class.html#MakeSubmitUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.NewItemPage.__init__ qm.test.web.web.NewItemPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.NewItemPage.GetClassDescriptions qm.test.web.web.NewItemPage-class.html#GetClassDescriptions qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.NewItemPage.GetTitle qm.test.web.web.NewItemPage-class.html#GetTitle qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.NewSuitePage qm.test.web.web.NewSuitePage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.NewSuitePage.__init__ qm.test.web.web.NewSuitePage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.QMTestPage qm.test.web.web.QMTestPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.QMTestPage.__init__ qm.test.web.web.QMTestPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.QMTestReportPage qm.test.web.web.QMTestReportPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestReportPage.GenerateHtmlHeader qm.test.web.web.QMTestReportPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.QMTestReportPage.__init__ qm.test.web.web.QMTestReportPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.QMTestReportPage.GetRunDatabase qm.test.web.web.QMTestReportPage-class.html#GetRunDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestReportPage.GenerateStartBody qm.test.web.web.QMTestReportPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.test.web.web.QMTestReportPage.FormatTimeIso qm.test.web.web.QMTestReportPage-class.html#FormatTimeIso qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.QMTestReportPage.GetResultURL qm.test.web.web.QMTestReportPage-class.html#GetResultURL qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.QMTestServer qm.test.web.web.QMTestServer-class.html qm.test.web.web.QMTestServer.HandleSubmitExpectationsForm qm.test.web.web.QMTestServer-class.html#HandleSubmitExpectationsForm qm.test.web.web.QMTestServer.HandleEditContext qm.test.web.web.QMTestServer-class.html#HandleEditContext qm.test.web.web.QMTestServer.MakeNewResource qm.test.web.web.QMTestServer-class.html#MakeNewResource qm.test.web.web.QMTestServer.HandleDeleteItem qm.test.web.web.QMTestServer-class.html#HandleDeleteItem qm.test.web.web.QMTestServer.HandleClearResults qm.test.web.web.QMTestServer-class.html#HandleClearResults qm.test.web.web.QMTestServer.GetExpectedOutcomes qm.test.web.web.QMTestServer-class.html#GetExpectedOutcomes qm.test.web.web.QMTestServer.HandleSubmitExpectations qm.test.web.web.QMTestServer-class.html#HandleSubmitExpectations qm.test.web.web.QMTestServer.HandleDir qm.test.web.web.QMTestServer-class.html#HandleDir qm.test.web.web.QMTestServer.HandleSubmitSuite qm.test.web.web.QMTestServer-class.html#HandleSubmitSuite qm.test.web.web.QMTestServer.HandleSaveContext qm.test.web.web.QMTestServer-class.html#HandleSaveContext qm.test.web.web.QMTestServer.HandleLoadResults qm.test.web.web.QMTestServer-class.html#HandleLoadResults qm.test.web.web.QMTestServer.__init__ qm.test.web.web.QMTestServer-class.html#__init__ qm.test.web.web.QMTestServer.MakeNewTest qm.test.web.web.QMTestServer-class.html#MakeNewTest qm.test.web.web.QMTestServer.HandleRunTests qm.test.web.web.QMTestServer-class.html#HandleRunTests qm.test.web.web.QMTestServer._HandleRoot qm.test.web.web.QMTestServer-class.html#_HandleRoot qm.test.web.web.QMTestServer.HandleSubmitItem qm.test.web.web.QMTestServer-class.html#HandleSubmitItem qm.test.web.web.QMTestServer.HandleShowResultReport qm.test.web.web.QMTestServer-class.html#HandleShowResultReport qm.test.web.web.QMTestServer.GetContext qm.test.web.web.QMTestServer-class.html#GetContext qm.test.web.web.QMTestServer.HandleNewTest qm.test.web.web.QMTestServer-class.html#HandleNewTest qm.test.web.web.QMTestServer.HandleNewSuite qm.test.web.web.QMTestServer-class.html#HandleNewSuite qm.test.web.web.QMTestServer.GetResultsStream qm.test.web.web.QMTestServer-class.html#GetResultsStream qm.test.web.web.QMTestServer.HandleShowResult qm.test.web.web.QMTestServer-class.html#HandleShowResult qm.test.web.web.QMTestServer.HandleSubmitContext qm.test.web.web.QMTestServer-class.html#HandleSubmitContext qm.test.web.web.QMTestServer.HandleCreateSuite qm.test.web.web.QMTestServer-class.html#HandleCreateSuite qm.test.web.web.QMTestServer.HandleLoadExpectations qm.test.web.web.QMTestServer-class.html#HandleLoadExpectations qm.test.web.web.QMTestServer.HandleShowItemReport qm.test.web.web.QMTestServer-class.html#HandleShowItemReport qm.test.web.web.QMTestServer.HandleSubmitExpectation qm.test.web.web.QMTestServer-class.html#HandleSubmitExpectation qm.test.web.web.QMTestServer.GetDatabase qm.test.web.web.QMTestServer-class.html#GetDatabase qm.test.web.web.QMTestServer.GetRunDatabase qm.test.web.web.QMTestServer-class.html#GetRunDatabase qm.test.web.web.QMTestServer.HandleShutdown qm.test.web.web.QMTestServer-class.html#HandleShutdown qm.test.web.web.QMTestServer.GetHTMLClassForOutcome qm.test.web.web.QMTestServer-class.html#GetHTMLClassForOutcome qm.test.web.web.QMTestServer._ClosePopupAndRedirect qm.test.web.web.QMTestServer-class.html#_ClosePopupAndRedirect qm.test.web.web.QMTestServer.HandleSetExpectation qm.test.web.web.QMTestServer-class.html#HandleSetExpectation qm.test.web.web.QMTestServer.HandleSaveExpectations qm.test.web.web.QMTestServer-class.html#HandleSaveExpectations qm.test.web.web.QMTestServer.HandleDeleteSuite qm.test.web.web.QMTestServer-class.html#HandleDeleteSuite qm.test.web.web.QMTestServer.HandleLoadContext qm.test.web.web.QMTestServer-class.html#HandleLoadContext qm.test.web.web.QMTestServer.GetExpectationDatabase qm.test.web.web.QMTestServer-class.html#GetExpectationDatabase qm.test.web.web.QMTestServer.HandleSubmitContextFile qm.test.web.web.QMTestServer-class.html#HandleSubmitContextFile qm.test.web.web.QMTestServer.HandleDirReport qm.test.web.web.QMTestServer-class.html#HandleDirReport qm.test.web.web.QMTestServer.HandleShowResults qm.test.web.web.QMTestServer-class.html#HandleShowResults qm.test.web.web.QMTestServer.HandleSaveResults qm.test.web.web.QMTestServer-class.html#HandleSaveResults qm.test.web.web.QMTestServer.HandleShowItem qm.test.web.web.QMTestServer-class.html#HandleShowItem qm.test.web.web.QMTestServer.HandleEditSuite qm.test.web.web.QMTestServer-class.html#HandleEditSuite qm.test.web.web.QMTestServer.HandleShowSuite qm.test.web.web.QMTestServer-class.html#HandleShowSuite qm.test.web.web.QMTestServer.HandleStopTests qm.test.web.web.QMTestServer-class.html#HandleStopTests qm.test.web.web.QMTestServer.HandleNewResource qm.test.web.web.QMTestServer-class.html#HandleNewResource qm.test.web.web.QMTestServer.HandleSubmitResults qm.test.web.web.QMTestServer-class.html#HandleSubmitResults qm.test.web.web.ResultPage qm.test.web.web.ResultPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.ResultPage.GetRunURL qm.test.web.web.ResultPage-class.html#GetRunURL qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.ResultPage.__init__ qm.test.web.web.ResultPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.ResultPage.GetResultURL qm.test.web.web.ResultPage-class.html#GetResultURL qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.SetExpectationPage qm.test.web.web.SetExpectationPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.SetExpectationPage.__init__ qm.test.web.web.SetExpectationPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.ShowItemPage qm.test.web.web.ShowItemPage-class.html qm.test.web.web.ShowItemPage.MakeEditUrl qm.test.web.web.ShowItemPage-class.html#MakeEditUrl qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.test.web.web.ShowItemPage.MakeShowUrl qm.test.web.web.ShowItemPage-class.html#MakeShowUrl qm.test.web.web.ShowItemPage.MakeSubmitUrl qm.test.web.web.ShowItemPage-class.html#MakeSubmitUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.ShowItemPage.__init__ qm.test.web.web.ShowItemPage-class.html#__init__ qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.test.web.web.ShowItemPage.FormatFieldValue qm.test.web.web.ShowItemPage-class.html#FormatFieldValue qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.ShowItemPage.GetClassDescription qm.test.web.web.ShowItemPage-class.html#GetClassDescription qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.test.web.web.ShowItemPage.GetBriefClassDescription qm.test.web.web.ShowItemPage-class.html#GetBriefClassDescription qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.ShowItemPage.MakeDeleteScript qm.test.web.web.ShowItemPage-class.html#MakeDeleteScript qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.ShowItemPage.GetTitle qm.test.web.web.ShowItemPage-class.html#GetTitle qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.ShowItemPage.MakeRunUrl qm.test.web.web.ShowItemPage-class.html#MakeRunUrl qm.test.web.web.ShowItemReportPage qm.test.web.web.ShowItemReportPage-class.html qm.test.web.web.ShowItemReportPage.FormatFieldValue qm.test.web.web.ShowItemReportPage-class.html#FormatFieldValue qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.test.web.web.ShowItemReportPage.MakeShowUrl qm.test.web.web.ShowItemReportPage-class.html#MakeShowUrl qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.ShowItemReportPage.__init__ qm.test.web.web.ShowItemReportPage-class.html#__init__ qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.ShowItemReportPage.GetClassDescription qm.test.web.web.ShowItemReportPage-class.html#GetClassDescription qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestReportPage.GenerateHtmlHeader qm.test.web.web.QMTestReportPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.test.web.web.ShowItemReportPage.GetBriefClassDescription qm.test.web.web.ShowItemReportPage-class.html#GetBriefClassDescription qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.ShowItemReportPage.GetDetailUrl qm.test.web.web.ShowItemReportPage-class.html#GetDetailUrl qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.QMTestReportPage.GetRunDatabase qm.test.web.web.QMTestReportPage-class.html#GetRunDatabase qm.test.web.web.ShowItemReportPage.GetTitle qm.test.web.web.ShowItemReportPage-class.html#GetTitle qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestReportPage.GenerateStartBody qm.test.web.web.QMTestReportPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.test.web.web.QMTestReportPage.FormatTimeIso qm.test.web.web.QMTestReportPage-class.html#FormatTimeIso qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.ShowItemReportPage.GetResults qm.test.web.web.ShowItemReportPage-class.html#GetResults qm.test.web.web.QMTestReportPage.GetResultURL qm.test.web.web.QMTestReportPage-class.html#GetResultURL qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.test.web.web.ShowSuitePage qm.test.web.web.ShowSuitePage-class.html qm.test.web.web.ShowSuitePage.MakeEditUrl qm.test.web.web.ShowSuitePage-class.html#MakeEditUrl qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.QMTestPage.GetRefreshDelay qm.test.web.web.QMTestPage-class.html#GetRefreshDelay qm.test.web.web.ShowSuitePage.__init__ qm.test.web.web.ShowSuitePage-class.html#__init__ qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.ShowSuitePage.MakeDeleteScript qm.test.web.web.ShowSuitePage-class.html#MakeDeleteScript qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.QMTestPage.IsFinished qm.test.web.web.QMTestPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.ShowSuitePage.MakeRunUrl qm.test.web.web.ShowSuitePage-class.html#MakeRunUrl qm.test.web.web.StorageResultsStream qm.test.web.web.StorageResultsStream-class.html qm.extension.Extension.__metaclass__ qm.extension.Extension.Type-class.html qm.extension.Extension.Write qm.extension.Extension-class.html#Write qm.test.web.web.StorageResultsStream.Start qm.test.web.web.StorageResultsStream-class.html#Start qm.test.web.web.StorageResultsStream.GetAnnotations qm.test.web.web.StorageResultsStream-class.html#GetAnnotations qm.extension.Extension.Type qm.extension.Extension.Type-class.html qm.test.web.web.StorageResultsStream.__init__ qm.test.web.web.StorageResultsStream-class.html#__init__ qm.extension.Extension._allow_arg_names_matching_class_vars qm.extension.Extension-class.html#_allow_arg_names_matching_class_vars qm.test.web.web.StorageResultsStream.WriteResult qm.test.web.web.StorageResultsStream-class.html#WriteResult qm.extension.Extension.__getattr__ qm.extension.Extension-class.html#__getattr__ qm.extension.Extension.arguments qm.extension.Extension-class.html#arguments qm.extension.Extension.MakeDomDocument qm.extension.Extension-class.html#MakeDomDocument qm.test.result_stream.ResultStream.expected_outcomes qm.test.result_stream.ResultStream-class.html#expected_outcomes qm.test.web.web.StorageResultsStream.Summarize qm.test.web.web.StorageResultsStream-class.html#Summarize qm.test.web.web.StorageResultsStream.GetTestResultsInOrder qm.test.web.web.StorageResultsStream-class.html#GetTestResultsInOrder qm.test.web.web.StorageResultsStream.GetResult qm.test.web.web.StorageResultsStream-class.html#GetResult qm.test.result_stream.ResultStream._GetExpectedOutcome qm.test.result_stream.ResultStream-class.html#_GetExpectedOutcome qm.test.web.web.StorageResultsStream.GetResourceResults qm.test.web.web.StorageResultsStream-class.html#GetResourceResults qm.extension.Extension.GetClassName qm.extension.Extension-class.html#GetClassName qm.test.result_stream.ResultStream._argument_dictionary qm.test.result_stream.ResultStream-class.html#_argument_dictionary qm.test.result_stream.ResultStream.kind qm.test.result_stream.ResultStream-class.html#kind qm.test.result_stream.ResultStream.WriteAllAnnotations qm.test.result_stream.ResultStream-class.html#WriteAllAnnotations qm.test.web.web.StorageResultsStream.IsFinished qm.test.web.web.StorageResultsStream-class.html#IsFinished qm.extension.Extension.MakeDomElement qm.extension.Extension-class.html#MakeDomElement qm.test.result_stream.ResultStream._argument_list qm.test.result_stream.ResultStream-class.html#_argument_list qm.extension.Extension.GetExplicitArguments qm.extension.Extension-class.html#GetExplicitArguments qm.test.web.web.StorageResultsStream.GetTestResults qm.test.web.web.StorageResultsStream-class.html#GetTestResults qm.test.web.web.StorageResultsStream.WriteAnnotation qm.test.web.web.StorageResultsStream-class.html#WriteAnnotation qm.test.web.web.TestResultsPage qm.test.web.web.TestResultsPage-class.html qm.test.web.web.TestResultsPage.GetResultsWithOutcome qm.test.web.web.TestResultsPage-class.html#GetResultsWithOutcome qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.test.web.web.DefaultDtmlPage.GetOutcomePercentages qm.test.web.web.DefaultDtmlPage-class.html#GetOutcomePercentages qm.test.web.web.DefaultDtmlPage.outcomes qm.test.web.web.DefaultDtmlPage-class.html#outcomes qm.test.web.web.DefaultDtmlPage.GetResultsByOutcome qm.test.web.web.DefaultDtmlPage-class.html#GetResultsByOutcome qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.test.web.web.TestResultsPage.GetTotalUnexpected qm.test.web.web.TestResultsPage-class.html#GetTotalUnexpected qm.test.web.web.TestResultsPage.GetRefreshDelay qm.test.web.web.TestResultsPage-class.html#GetRefreshDelay qm.test.web.web.DefaultDtmlPage.IsLabelInDirectory qm.test.web.web.DefaultDtmlPage-class.html#IsLabelInDirectory qm.test.web.web.DefaultDtmlPage.EXPECTATION_KINDS qm.test.web.web.DefaultDtmlPage-class.html#EXPECTATION_KINDS qm.web.DtmlPage.web qm.web-module.html qm.test.web.web.TestResultsPage.GetRelativeResults qm.test.web.web.TestResultsPage-class.html#GetRelativeResults qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.test.web.web.DefaultDtmlPage.NEGATIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#NEGATIVE_UNEXPECTED qm.test.web.web.QMTestPage.GenerateHtmlHeader qm.test.web.web.QMTestPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.test.web.web.TestResultsPage.__init__ qm.test.web.web.TestResultsPage-class.html#__init__ qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.test.web.web.DefaultDtmlPage.EXPECTED qm.test.web.web.DefaultDtmlPage-class.html#EXPECTED qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.test.web.web.TestResultsPage.GetDetailUrl qm.test.web.web.TestResultsPage-class.html#GetDetailUrl qm.test.web.web.DefaultDtmlPage.GetDatabase qm.test.web.web.DefaultDtmlPage-class.html#GetDatabase qm.test.web.web.DefaultDtmlPage.GetName qm.test.web.web.DefaultDtmlPage-class.html#GetName qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.test.web.web.DefaultDtmlPage.HasModifiableExpectations qm.test.web.web.DefaultDtmlPage-class.html#HasModifiableExpectations qm.test.web.web.DefaultDtmlPage.html_generator qm.test.web.web.DefaultDtmlPage-class.html#html_generator qm.test.web.web.TestResultsPage.GetOutcomes qm.test.web.web.TestResultsPage-class.html#GetOutcomes qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.test.web.web.DefaultDtmlPage.FormatId qm.test.web.web.DefaultDtmlPage-class.html#FormatId qm.test.web.web.QMTestPage.GenerateStartBody qm.test.web.web.QMTestPage-class.html#GenerateStartBody qm.test.web.web.DefaultDtmlPage.GetMainPageUrl qm.test.web.web.DefaultDtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.test.web.web.DefaultDtmlPage.MakeListingUrl qm.test.web.web.DefaultDtmlPage-class.html#MakeListingUrl qm.test.web.web.TestResultsPage.GetUnexpectedCount qm.test.web.web.TestResultsPage-class.html#GetUnexpectedCount qm.test.web.web.TestResultsPage.GetTotal qm.test.web.web.TestResultsPage-class.html#GetTotal qm.test.web.web.TestResultsPage.IsFinished qm.test.web.web.TestResultsPage-class.html#IsFinished qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.test.web.web.TestResultsPage.GetCount qm.test.web.web.TestResultsPage-class.html#GetCount qm.test.web.web.QMTestPage.GetExpectationUrl qm.test.web.web.QMTestPage-class.html#GetExpectationUrl qm.test.web.web.DefaultDtmlPage.POSITIVE_UNEXPECTED qm.test.web.web.DefaultDtmlPage-class.html#POSITIVE_UNEXPECTED qm.trace.Tracer qm.trace.Tracer-class.html qm.trace.Tracer.Write qm.trace.Tracer-class.html#Write qm.trace.Tracer.GetThreshold qm.trace.Tracer-class.html#GetThreshold qm.trace.Tracer.prefix qm.trace.Tracer-class.html#prefix qm.trace.Tracer.SetThreshold qm.trace.Tracer-class.html#SetThreshold qm.trace.Tracer.__init__ qm.trace.Tracer-class.html#__init__ qm.user.AccountDisabledError qm.user.AccountDisabledError-class.html qm.user.AuthenticationError qm.user.AuthenticationError-class.html qm.user.Authenticator qm.user.Authenticator-class.html qm.user.Authenticator.AuthenticateDefaultUser qm.user.Authenticator-class.html#AuthenticateDefaultUser qm.user.Authenticator.AuthenticateWebRequest qm.user.Authenticator-class.html#AuthenticateWebRequest qm.user.DefaultAuthenticator qm.user.DefaultAuthenticator-class.html qm.user.DefaultAuthenticator.AuthenticateDefaultUser qm.user.DefaultAuthenticator-class.html#AuthenticateDefaultUser qm.user.DefaultAuthenticator.AuthenticateWebRequest qm.user.DefaultAuthenticator-class.html#AuthenticateWebRequest qm.user.DefaultDatabase qm.user.DefaultDatabase-class.html qm.user.DefaultDatabase.GetDefaultUserId qm.user.DefaultDatabase-class.html#GetDefaultUserId qm.user.DefaultDatabase.__getitem__ qm.user.DefaultDatabase-class.html#__getitem__ qm.user.DefaultDatabase.get qm.user.DefaultDatabase-class.html#get qm.user.DefaultDatabase.keys qm.user.DefaultDatabase-class.html#keys qm.user.DefaultDatabase.GetGroupIds qm.user.DefaultDatabase-class.html#GetGroupIds qm.user.DefaultDatabase.GetGroup qm.user.DefaultDatabase-class.html#GetGroup qm.user.DefaultDatabase.default_user qm.user.DefaultDatabase-class.html#default_user qm.user.Group qm.user.Group-class.html qm.user.Group.__delitem__ qm.user.Group-class.html#__delitem__ qm.user.Group.__getitem__ qm.user.Group-class.html#__getitem__ qm.user.Group.GetId qm.user.Group-class.html#GetId qm.user.Group.__setitem__ qm.user.Group-class.html#__setitem__ qm.user.Group.__len__ qm.user.Group-class.html#__len__ qm.user.Group.remove qm.user.Group-class.html#remove qm.user.Group.__init__ qm.user.Group-class.html#__init__ qm.user.Group.append qm.user.Group-class.html#append qm.user.User qm.user.User-class.html qm.user.User.SetInfoProperty qm.user.User-class.html#SetInfoProperty qm.user.User.GetConfigurationProperty qm.user.User-class.html#GetConfigurationProperty qm.user.User.IsEnabled qm.user.User-class.html#IsEnabled qm.user.User.GetId qm.user.User-class.html#GetId qm.user.User.SetConfigurationProperty qm.user.User-class.html#SetConfigurationProperty qm.user.User.GetRole qm.user.User-class.html#GetRole qm.user.User.GetInfoProperty qm.user.User-class.html#GetInfoProperty qm.user.User.__init__ qm.user.User-class.html#__init__ qm.user.XmlDatabase qm.user.XmlDatabase-class.html qm.user.XmlDatabase.GetDefaultUserId qm.user.XmlDatabase-class.html#GetDefaultUserId qm.user.XmlDatabase.__getitem__ qm.user.XmlDatabase-class.html#__getitem__ qm.user.XmlDatabase.get qm.user.XmlDatabase-class.html#get qm.user.XmlDatabase.keys qm.user.XmlDatabase-class.html#keys qm.user.XmlDatabase.GetGroupIds qm.user.XmlDatabase-class.html#GetGroupIds qm.user.XmlDatabase.Write qm.user.XmlDatabase-class.html#Write qm.user.XmlDatabase.GetGroup qm.user.XmlDatabase-class.html#GetGroup qm.user.XmlDatabase.__init__ qm.user.XmlDatabase-class.html#__init__ qm.user.XmlDatabaseAuthenticator qm.user.XmlDatabaseAuthenticator-class.html qm.user.XmlDatabaseAuthenticator.AuthenticatePassword qm.user.XmlDatabaseAuthenticator-class.html#AuthenticatePassword qm.user.XmlDatabaseAuthenticator.AuthenticateDefaultUser qm.user.XmlDatabaseAuthenticator-class.html#AuthenticateDefaultUser qm.user.XmlDatabaseAuthenticator.__init__ qm.user.XmlDatabaseAuthenticator-class.html#__init__ qm.user.XmlDatabaseAuthenticator.AuthenticateWebRequest qm.user.XmlDatabaseAuthenticator-class.html#AuthenticateWebRequest qm.user.XmlDatabaseError qm.user.XmlDatabaseError-class.html qm.web.AddressInUseError qm.web.AddressInUseError-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.web.CGIWebRequest qm.web.CGIWebRequest-class.html qm.web.CGIWebRequest.GetUrl qm.web.CGIWebRequest-class.html#GetUrl qm.web.CGIWebRequest.__getitem__ qm.web.CGIWebRequest-class.html#__getitem__ qm.web.CGIWebRequest.keys qm.web.CGIWebRequest-class.html#keys qm.web.CGIWebRequest.has_key qm.web.CGIWebRequest-class.html#has_key qm.web.CGIWebRequest.copy qm.web.CGIWebRequest-class.html#copy qm.web.CGIWebRequest.__init__ qm.web.CGIWebRequest-class.html#__init__ qm.web.DtmlPage qm.web.DtmlPage-class.html qm.web.DtmlPage.MakeSpacer qm.web.DtmlPage-class.html#MakeSpacer qm.web.DtmlPage.html_stylesheet qm.web.DtmlPage-class.html#html_stylesheet qm.web.DtmlPage.default_class qm.web.DtmlPage-class.html qm.web.DtmlPage.MakeImageUrl qm.web.DtmlPage-class.html#MakeImageUrl qm.web.DtmlPage.__init__ qm.web.DtmlPage-class.html#__init__ qm.web.DtmlPage.web qm.web-module.html qm.web.DtmlPage.UserIsInGroup qm.web.DtmlPage-class.html#UserIsInGroup qm.web.DtmlPage.GenerateHtmlHeader qm.web.DtmlPage-class.html#GenerateHtmlHeader qm.web.DtmlPage.GenerateXMLHeader qm.web.DtmlPage-class.html#GenerateXMLHeader qm.web.DtmlPage.WebRequest qm.web.DtmlPage-class.html#WebRequest qm.web.DtmlPage.GenerateEndBody qm.web.DtmlPage-class.html#GenerateEndBody qm.web.DtmlPage.__call__ qm.web.DtmlPage-class.html#__call__ qm.web.DtmlPage.qm_bug_system_url qm.web.DtmlPage-class.html#qm_bug_system_url qm.web.DtmlPage.GenerateStartScript qm.web.DtmlPage-class.html#GenerateStartScript qm.web.DtmlPage.GenerateEndScript qm.web.DtmlPage-class.html#GenerateEndScript qm.web.DtmlPage.GetMainPageUrl qm.web.DtmlPage-class.html#GetMainPageUrl qm.web.DtmlPage.GenerateStartBody qm.web.DtmlPage-class.html#GenerateStartBody qm.web.DtmlPage.MakeRule qm.web.DtmlPage-class.html#MakeRule qm.web.DtmlPage.common_javascript qm.web.DtmlPage-class.html#common_javascript qm.web.DtmlPage.MakeButton qm.web.DtmlPage-class.html#MakeButton qm.web.DtmlPage.MakeLoginForm qm.web.DtmlPage-class.html#MakeLoginForm qm.web.DtmlPage.GetProgramName qm.web.DtmlPage-class.html#GetProgramName qm.web.HTTPServer qm.web.HTTPServer-class.html qm.web.HTTPServer.server_bind qm.web.HTTPServer-class.html#server_bind qm.web.HttpRedirect qm.web.HttpRedirect-class.html qm.web.HttpRedirect.__init__ qm.web.HttpRedirect-class.html#__init__ qm.web.InvalidSessionError qm.web.InvalidSessionError-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.web.NoSessionError qm.web.NoSessionError-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.web.PrivilegedPortError qm.web.PrivilegedPortError-class.html qm.common.QMException.__init__ qm.common.QMException-class.html#__init__ qm.web.Session qm.web.Session-class.html qm.web.Session.GetId qm.web.Session-class.html#GetId qm.web.Session.GetUserId qm.web.Session-class.html#GetUserId qm.web.Session.GetUser qm.web.Session-class.html#GetUser qm.web.Session.Touch qm.web.Session-class.html#Touch qm.web.Session.IsExpired qm.web.Session-class.html#IsExpired qm.web.Session.IsDefaultUser qm.web.Session-class.html#IsDefaultUser qm.web.Session.Validate qm.web.Session-class.html#Validate qm.web.Session.__init__ qm.web.Session-class.html#__init__ qm.web.WebRequest qm.web.WebRequest-class.html qm.web.WebRequest.GetUrl qm.web.WebRequest-class.html#GetUrl qm.web.WebRequest.GetSession qm.web.WebRequest-class.html#GetSession qm.web.WebRequest.GetSessionId qm.web.WebRequest-class.html#GetSessionId qm.web.WebRequest.__getitem__ qm.web.WebRequest-class.html#__getitem__ qm.web.WebRequest.__delitem__ qm.web.WebRequest-class.html#__delitem__ qm.web.WebRequest.keys qm.web.WebRequest-class.html#keys qm.web.WebRequest.items qm.web.WebRequest-class.html#items qm.web.WebRequest.__str__ qm.web.WebRequest-class.html#__str__ qm.web.WebRequest.get qm.web.WebRequest-class.html#get qm.web.WebRequest.GetScriptName qm.web.WebRequest-class.html#GetScriptName qm.web.WebRequest.__setitem__ qm.web.WebRequest-class.html#__setitem__ qm.web.WebRequest.has_key qm.web.WebRequest-class.html#has_key qm.web.WebRequest.AsForm qm.web.WebRequest-class.html#AsForm qm.web.WebRequest.__init__ qm.web.WebRequest-class.html#__init__ qm.web.WebRequest.SetSessionId qm.web.WebRequest-class.html#SetSessionId qm.web.WebRequest.copy qm.web.WebRequest-class.html#copy qm.web.WebRequest.AsUrl qm.web.WebRequest-class.html#AsUrl qm.web.WebRequestHandler qm.web.WebRequestHandler-class.html qm.web.WebRequestHandler.__HandlePageCacheRequest qm.web.WebRequestHandler-class.html#__HandlePageCacheRequest qm.web.WebRequestHandler.__HandleFileRequest qm.web.WebRequestHandler-class.html#__HandleFileRequest qm.web.WebRequestHandler.__HandleSessionCacheRequest qm.web.WebRequestHandler-class.html#__HandleSessionCacheRequest qm.web.WebRequestHandler.__HandleRequest qm.web.WebRequestHandler-class.html#__HandleRequest qm.web.WebRequestHandler.do_GET qm.web.WebRequestHandler-class.html#do_GET qm.web.WebRequestHandler.__HandleScriptRequest qm.web.WebRequestHandler-class.html#__HandleScriptRequest qm.web.WebRequestHandler.log_message qm.web.WebRequestHandler-class.html#log_message BaseHTTPServer.BaseHTTPRequestHandler.MessageClass mimetools.Message-class.html qm.web.WebRequestHandler.do_POST qm.web.WebRequestHandler-class.html#do_POST qm.web.WebServer qm.web.WebServer-class.html qm.web.WebServer._HandleRoot qm.web.WebServer-class.html#_HandleRoot qm.web.WebServer.IsScript qm.web.WebServer-class.html#IsScript qm.web.WebServer.RequestShutdown qm.web.WebServer-class.html#RequestShutdown qm.web.WebServer.TranslateRequest qm.web.WebServer-class.html#TranslateRequest qm.web.HTTPServer.server_bind qm.web.HTTPServer-class.html#server_bind qm.web.WebServer.MakePopupDialog qm.web.WebServer-class.html#MakePopupDialog qm.web.WebServer.handle_error qm.web.WebServer-class.html#handle_error qm.web.WebServer.__init__ qm.web.WebServer-class.html#__init__ qm.web.WebServer.Run qm.web.WebServer-class.html#Run qm.web.WebServer.__GetPathForCachedPage qm.web.WebServer-class.html#__GetPathForCachedPage qm.web.WebServer.MakeConfirmationDialog qm.web.WebServer-class.html#MakeConfirmationDialog qm.web.WebServer.HandleNoSessionError qm.web.WebServer-class.html#HandleNoSessionError qm.web.WebServer.ProcessScript qm.web.WebServer-class.html#ProcessScript qm.web.WebServer.MakeButtonForCachedPopup qm.web.WebServer-class.html#MakeButtonForCachedPopup qm.web.WebServer.Bind qm.web.WebServer-class.html#Bind qm.web.WebServer.RegisterScript qm.web.WebServer-class.html#RegisterScript qm.web.WebServer.GetServerAddress qm.web.WebServer-class.html#GetServerAddress qm.web.WebServer.GetCachedPage qm.web.WebServer-class.html#GetCachedPage qm.web.WebServer._HandleProblems qm.web.WebServer-class.html#_HandleProblems qm.web.WebServer.GetTemporaryAttachmentStore qm.web.WebServer-class.html#GetTemporaryAttachmentStore qm.web.WebServer.CachePage qm.web.WebServer-class.html#CachePage qm.web.WebServer.RegisterPathTranslation qm.web.WebServer-class.html#RegisterPathTranslation qm.web.WebServer.LogMessage qm.web.WebServer-class.html#LogMessage random.Random random.Random-class.html random.Random.paretovariate random.Random-class.html#paretovariate random.Random.shuffle random.Random-class.html#shuffle random.Random.randrange random.Random-class.html#randrange random.Random.betavariate random.Random-class.html#betavariate random.Random.__reduce__ random.Random-class.html#__reduce__ random.Random.__getstate__ random.Random-class.html#__getstate__ random.Random.normalvariate random.Random-class.html#normalvariate random.Random.sample random.Random-class.html#sample random.Random.seed random.Random-class.html#seed random.Random.weibullvariate random.Random-class.html#weibullvariate random.Random.__init__ random.Random-class.html#__init__ random.Random.randint random.Random-class.html#randint random.Random.vonmisesvariate random.Random-class.html#vonmisesvariate random.Random.gammavariate random.Random-class.html#gammavariate random.Random.uniform random.Random-class.html#uniform random.Random.expovariate random.Random-class.html#expovariate random.Random._randbelow random.Random-class.html#_randbelow random.Random.setstate random.Random-class.html#setstate random.Random.lognormvariate random.Random-class.html#lognormvariate random.Random.__setstate__ random.Random-class.html#__setstate__ random.Random.gauss random.Random-class.html#gauss random.Random.choice random.Random-class.html#choice random.Random.VERSION random.Random-class.html#VERSION random.Random.getstate random.Random-class.html#getstate random.SystemRandom random.SystemRandom-class.html random.Random.paretovariate random.Random-class.html#paretovariate random.Random.shuffle random.Random-class.html#shuffle random.Random.randrange random.Random-class.html#randrange random.Random.betavariate random.Random-class.html#betavariate random.SystemRandom._stub random.SystemRandom-class.html#_stub random.SystemRandom.random random.SystemRandom-class.html#random random.Random.__reduce__ random.Random-class.html#__reduce__ random.Random.normalvariate random.Random-class.html#normalvariate random.Random.sample random.Random-class.html#sample random.SystemRandom.seed random.SystemRandom-class.html#seed random.Random.weibullvariate random.Random-class.html#weibullvariate random.Random.__init__ random.Random-class.html#__init__ random.Random.randint random.Random-class.html#randint random.Random.vonmisesvariate random.Random-class.html#vonmisesvariate random.Random.gammavariate random.Random-class.html#gammavariate random.Random.uniform random.Random-class.html#uniform random.Random.expovariate random.Random-class.html#expovariate random.Random._randbelow random.Random-class.html#_randbelow random.Random.__getstate__ random.Random-class.html#__getstate__ random.SystemRandom.getrandbits random.SystemRandom-class.html#getrandbits random.SystemRandom.setstate random.SystemRandom-class.html#setstate random.Random.lognormvariate random.Random-class.html#lognormvariate random.Random.__setstate__ random.Random-class.html#__setstate__ random.Random.gauss random.Random-class.html#gauss random.Random.choice random.Random-class.html#choice random.Random.VERSION random.Random-class.html#VERSION random.SystemRandom.jumpahead random.SystemRandom-class.html#jumpahead random.SystemRandom.getstate random.SystemRandom-class.html#getstate random.SystemRandom._notimplemented random.SystemRandom-class.html#_notimplemented random.WichmannHill random.WichmannHill-class.html random.Random.paretovariate random.Random-class.html#paretovariate random.Random.shuffle random.Random-class.html#shuffle random.Random.randrange random.Random-class.html#randrange random.WichmannHill.__whseed random.WichmannHill-class.html#__whseed random.Random.betavariate random.Random-class.html#betavariate random.WichmannHill.random random.WichmannHill-class.html#random random.Random.__reduce__ random.Random-class.html#__reduce__ random.Random.normalvariate random.Random-class.html#normalvariate random.Random.sample random.Random-class.html#sample random.WichmannHill.seed random.WichmannHill-class.html#seed random.Random.weibullvariate random.Random-class.html#weibullvariate random.Random.__init__ random.Random-class.html#__init__ random.Random.randint random.Random-class.html#randint random.WichmannHill.whseed random.WichmannHill-class.html#whseed random.Random.vonmisesvariate random.Random-class.html#vonmisesvariate random.Random.gammavariate random.Random-class.html#gammavariate random.Random.uniform random.Random-class.html#uniform random.Random.expovariate random.Random-class.html#expovariate random.Random._randbelow random.Random-class.html#_randbelow random.Random.__getstate__ random.Random-class.html#__getstate__ random.WichmannHill.setstate random.WichmannHill-class.html#setstate random.Random.lognormvariate random.Random-class.html#lognormvariate random.Random.__setstate__ random.Random-class.html#__setstate__ random.Random.gauss random.Random-class.html#gauss random.Random.choice random.Random-class.html#choice random.WichmannHill.VERSION random.WichmannHill-class.html#VERSION random.WichmannHill.jumpahead random.WichmannHill-class.html#jumpahead random.WichmannHill.getstate random.WichmannHill-class.html#getstate str str-class.html str.upper str-class.html#upper str.__getslice__ str-class.html#__getslice__ str.__ne__ str-class.html#__ne__ str.lstrip str-class.html#lstrip str.__str__ str-class.html#__str__ str.__getattribute__ str-class.html#__getattribute__ str.rpartition str-class.html#rpartition str.replace str-class.html#replace str.isdigit str-class.html#isdigit str.endswith str-class.html#endswith str.splitlines str-class.html#splitlines str.rfind str-class.html#rfind str.strip str-class.html#strip str.__rmul__ str-class.html#__rmul__ str.__lt__ str-class.html#__lt__ str.__getnewargs__ str-class.html#__getnewargs__ str.__rmod__ str-class.html#__rmod__ str.index str-class.html#index str.ljust str-class.html#ljust str.__new__ str-class.html#__new__ str.isalnum str-class.html#isalnum str.__contains__ str-class.html#__contains__ str.rindex str-class.html#rindex str.rsplit str-class.html#rsplit str.find str-class.html#find str.decode str-class.html#decode str.isalpha str-class.html#isalpha str.__eq__ str-class.html#__eq__ str.split str-class.html#split str.rstrip str-class.html#rstrip str.encode str-class.html#encode str.translate str-class.html#translate str.isspace str-class.html#isspace str.__len__ str-class.html#__len__ str.__repr__ str-class.html#__repr__ str.startswith str-class.html#startswith str.__getitem__ str-class.html#__getitem__ str.rjust str-class.html#rjust str.swapcase str-class.html#swapcase str.__hash__ str-class.html#__hash__ str.zfill str-class.html#zfill str.__add__ str-class.html#__add__ str.__gt__ str-class.html#__gt__ str.capitalize str-class.html#capitalize str.count str-class.html#count str.lower str-class.html#lower str.join str-class.html#join str.center str-class.html#center str.__mod__ str-class.html#__mod__ str.partition str-class.html#partition str.expandtabs str-class.html#expandtabs str.istitle str-class.html#istitle str.__le__ str-class.html#__le__ str.__mul__ str-class.html#__mul__ str.islower str-class.html#islower str.title str-class.html#title str.isupper str-class.html#isupper str.__ge__ str-class.html#__ge__ string.Template string.Template-class.html string.Template._invalid string.Template-class.html#_invalid string.Template.idpattern string.Template-class.html#idpattern string.Template.__metaclass__ string._TemplateMetaclass-class.html string.Template.safe_substitute string.Template-class.html#safe_substitute string.Template.pattern string.Template-class.html#pattern string.Template.delimiter string.Template-class.html#delimiter string.Template.substitute string.Template-class.html#substitute string.Template.__init__ string.Template-class.html#__init__ string._TemplateMetaclass string._TemplateMetaclass-class.html string._TemplateMetaclass.__init__ string._TemplateMetaclass-class.html#__init__ string._TemplateMetaclass.pattern string._TemplateMetaclass-class.html#pattern string._multimap string._multimap-class.html string._multimap.__init__ string._multimap-class.html#__init__ string._multimap.__getitem__ string._multimap-class.html#__getitem__ qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform_unix.SignalException-class.html0000664000076400007640000002315111122067146030365 0ustar stefanstefan qm.platform_unix.SignalException
Package qm :: Module platform_unix :: Class SignalException
[hide private]
[frames] | no frames]

Class SignalException

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  SignalException

An exception raised in response to a signal.

Instance Methods [hide private]
 
__init__(self, signal_number)
Create a new signal exception.
source code
 
GetSignalNumber(self)
Return the number of the signal that caused this exception.
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, signal_number)
(Constructor)

source code 

Create a new signal exception.

'signal_number' -- The signal number.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database-module.html0000664000076400007640000001120011122067145027334 0ustar stefanstefan qm.test.parameter_database
Package qm :: Package test :: Module parameter_database
[hide private]
[frames] | no frames]

Module parameter_database

source code

Classes [hide private]
  ParameterDatabase
A database that parametrizes another database.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.ShowItemPage-class.html0000664000076400007640000005602111122067151027243 0ustar stefanstefan qm.test.web.web.ShowItemPage
Package qm :: Package test :: Package web :: Module web :: Class ShowItemPage
[hide private]
[frames] | no frames]

Class ShowItemPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      ShowItemPage

DTML page for showing and editing tests and resources.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, item, edit, new, type, field_errors={})
Construct a new DTML context.
source code
 
GetTitle(self)
Return the page title for this page.
source code
 
FormatFieldValue(self, field)
Return an HTML rendering of the value for 'field'.
source code
 
GetClassDescription(self)
Return a full description of the test or resource class.
source code
 
GetBriefClassDescription(self)
Return a brief description of the test or resource class.
source code
 
MakeEditUrl(self)
Return the URL for editing this item.
source code
 
MakeRunUrl(self)
Return the URL for running this item.
source code
 
MakeShowUrl(self)
Return the URL for showing this item.
source code
 
MakeSubmitUrl(self)
Return the URL for submitting edits.
source code
 
MakeDeleteScript(self)
Make a script to confirm deletion of the test or resource.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, item, edit, new, type, field_errors={})
(Constructor)

source code 

Construct a new DTML context.

These parameters are also available in DTML under the same name:

'server' -- The 'QMTestServer' creating this page.

'item' -- The 'TestDescriptor' or 'ResourceDescriptor' for the test being shown.

'edit' -- True for editing the item; false for displaying it only.

'new' -- True for editing a newly-created item ('edit' is then also true).

'type' -- Either "test" or "resource".

'field_errors' -- A map from field names to corresponding error messages.

Overrides: web.DtmlPage.__init__

GetClassDescription(self)

source code 

Return a full description of the test or resource class.

returns -- The description, formatted as HTML.

GetBriefClassDescription(self)

source code 

Return a brief description of the test or resource class.

returns -- The brief description, formatted as HTML.

MakeDeleteScript(self)

source code 

Make a script to confirm deletion of the test or resource.

returns -- JavaScript source to handle deletion of the test or resource.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-everything.html0000664000076400007640000020345611122067144023641 0ustar stefanstefan Everything

Everything


All Classes

float
int
mimetools.Message
qm.attachment.Attachment
qm.attachment.AttachmentStore
qm.attachment.FileAttachmentStore
qm.attachment.TemporaryAttachmentStore
qm.cmdline.CommandError
qm.cmdline.CommandParser
qm.common.PythonException
qm.common.QMException
qm.common.RcConfiguration
qm.common.UserError
qm.db.Connection
qm.diagnostic.DiagnosticSet
qm.dist.command.build_extensions.build_extensions
qm.dist.command.install_extensions.install_extensions
qm.dist.distribution.Distribution
qm.executable.Executable
qm.executable.Filter
qm.executable.RedirectedExecutable
qm.executable.TimeoutExecutable
qm.extension.Extension
qm.extension.Extension.Type
qm.external.DocumentTemplate.DT_HTML.HTML
qm.external.DocumentTemplate.DT_HTML.HTMLDefault
qm.external.DocumentTemplate.DT_HTML.HTMLFile
qm.external.DocumentTemplate.DT_HTML.dtml_re_class
qm.external.DocumentTemplate.DT_If.Else
qm.external.DocumentTemplate.DT_If.If
qm.external.DocumentTemplate.DT_If.Unless
qm.external.DocumentTemplate.DT_In.InClass
qm.external.DocumentTemplate.DT_In.InFactory
qm.external.DocumentTemplate.DT_InSV.sequence_variables
qm.external.DocumentTemplate.DT_Let.Let
qm.external.DocumentTemplate.DT_Raise.Raise
qm.external.DocumentTemplate.DT_Return.DTReturn
qm.external.DocumentTemplate.DT_Return.ReturnTag
qm.external.DocumentTemplate.DT_String.File
qm.external.DocumentTemplate.DT_String.FileMixin
qm.external.DocumentTemplate.DT_String.String
qm.external.DocumentTemplate.DT_Try.Try
qm.external.DocumentTemplate.DT_Util.Eval
qm.external.DocumentTemplate.DT_Var.Call
qm.external.DocumentTemplate.DT_Var.Comment
qm.external.DocumentTemplate.DT_Var.Var
qm.external.DocumentTemplate.DT_With.With
qm.external.DocumentTemplate.VSEval.Eval
qm.external.DocumentTemplate.pDocumentTemplate.DictInstance
qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict
qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping
qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict
qm.fields.AttachmentField
qm.fields.BooleanField
qm.fields.ChoiceField
qm.fields.DictionaryField
qm.fields.EnumerationField
qm.fields.Field
qm.fields.IntegerField
qm.fields.PythonField
qm.fields.SetField
qm.fields.TextField
qm.fields.TimeField
qm.fields.TupleField
qm.fields.UploadAttachmentPage
qm.host.Host
qm.host.Host.Executable
qm.host.Host.Executable
qm.label.Label
qm.platform.MailError
qm.platform_unix.SignalException
qm.platform_win32.SignalException
qm.structured_text.Formatter
qm.structured_text.HtmlFormatter
qm.structured_text.StructuredTextProcessor
qm.structured_text.TextFormatter
qm.temporary_directory.TemporaryDirectory
qm.test.base.CouldNotLoadExtensionError
qm.test.classes.command.ExecTest
qm.test.classes.command.ExecTestBase
qm.test.classes.command.ShellCommandTest
qm.test.classes.command.ShellScriptTest
qm.test.classes.command_host.CommandHost
qm.test.classes.compilation_test.CompilationTest
qm.test.classes.compilation_test.CompiledResource
qm.test.classes.compilation_test.ExecutableTest
qm.test.classes.compilation_test_database.CompilationTest
qm.test.classes.compilation_test_database.CompilationTestDatabase
qm.test.classes.compiler.Compiler
qm.test.classes.compiler.CompilerExecutable
qm.test.classes.compiler.Diagnostic
qm.test.classes.compiler.EDG
qm.test.classes.compiler.GCC
qm.test.classes.compiler.SourcePosition
qm.test.classes.compiler_table.CompilerTable
qm.test.classes.compiler_test.CompilationStep
qm.test.classes.compiler_test.CompilerBase
qm.test.classes.compiler_test.CompilerTest
qm.test.classes.dejagnu_base.DejaGNUBase
qm.test.classes.dejagnu_stream.DejaGNUReader
qm.test.classes.dejagnu_stream.DejaGNUStream
qm.test.classes.dejagnu_test.DejaGNUTest
qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable
qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable
qm.test.classes.dg_test.DGTest
qm.test.classes.dg_test.DGTest.DGException
qm.test.classes.dir_run_database.DirRunDatabase
qm.test.classes.explicit_suite.ExplicitSuite
qm.test.classes.file.FileContentsTest
qm.test.classes.file.SubstitutionField
qm.test.classes.file_label.FileLabel
qm.test.classes.local_host.LocalHost
qm.test.classes.mount_database.MountDatabase
qm.test.classes.mount_database.MountDatabase.MountedSuite
qm.test.classes.pickle_result_stream.PickleResultReader
qm.test.classes.pickle_result_stream.PickleResultStream
qm.test.classes.previous_testrun.PreviousTestRun
qm.test.classes.process_target.ProcessTarget
qm.test.classes.process_target.ProcessTarget.QMTestExecutable
qm.test.classes.process_target.ProcessTarget.QMTestExecutable
qm.test.classes.python.BaseExceptionTest
qm.test.classes.python.ExceptionTest
qm.test.classes.python.ExecTest
qm.test.classes.python.StringExceptionTest
qm.test.classes.python_label.PythonLabel
qm.test.classes.rsh_target.RSHTarget
qm.test.classes.serial_target.SerialTarget
qm.test.classes.simulator.Simulator
qm.test.classes.sql_result_stream.SQLResultReader
qm.test.classes.sql_result_stream.SQLResultStream
qm.test.classes.ssh_host.RSHHost
qm.test.classes.ssh_host.SSHHost
qm.test.classes.temporary.TempDirectoryResource
qm.test.classes.tet_stream.TETStream
qm.test.classes.text_result_stream.TextResultStream
qm.test.classes.thread_target.LocalThread
qm.test.classes.thread_target.ThreadTarget
qm.test.classes.xml_database.TestFileError
qm.test.classes.xml_database.XMLDatabase
qm.test.classes.xml_expectation_database.XMLExpectationDatabase
qm.test.classes.xml_result_stream.XMLResultReader
qm.test.classes.xml_result_stream.XMLResultStream
qm.test.cmdline.QMTest
qm.test.command_thread.CommandThread
qm.test.context.Context
qm.test.context.ContextException
qm.test.context.ContextWrapper
qm.test.database.Database
qm.test.database.DatabaseError
qm.test.database.ItemDescriptor
qm.test.database.NoSuchItemError
qm.test.database.NoSuchResourceError
qm.test.database.NoSuchSuiteError
qm.test.database.NoSuchTestError
qm.test.database.ResourceDescriptor
qm.test.database.TestDescriptor
qm.test.directory_suite.DirectorySuite
qm.test.execution_engine.ExecutionEngine
qm.test.execution_engine.TerminationRequested
qm.test.execution_thread.ExecutionThread
qm.test.expectation_database.ExpectationDatabase
qm.test.file_database.ExtensionDatabase
qm.test.file_database.FileDatabase
qm.test.file_result_reader.FileResultReader
qm.test.file_result_reader.FileResultReader.InvalidFile
qm.test.file_result_stream.FileResultStream
qm.test.parameter_database.ParameterDatabase
qm.test.parameter_database.ParameterDatabase.ImplicitSuite
qm.test.parameter_database.ParameterDatabase.ParameterSuite
qm.test.parameter_database.ParameterDatabase.WrapperSuite
qm.test.reader_test_run.ReaderTestRun
qm.test.report.ReportGenerator
qm.test.resource.Resource
qm.test.resource_adapter.ResourceAdapter
qm.test.result.Result
qm.test.result_reader.ResultReader
qm.test.result_stream.ResultStream
qm.test.run_database.RunDatabase
qm.test.runnable.Runnable
qm.test.runnable.Runnable.ResourceField
qm.test.suite.Suite
qm.test.target.Target
qm.test.test.TargetGroupField
qm.test.test.Test
qm.test.test.Test.OutcomeField
qm.test.test.Test.OutcomeField
qm.test.test.Test.TestField
qm.test.test.Test.TestField
qm.test.test_run.TestRun
qm.test.web.web.ContextPage
qm.test.web.web.DefaultDtmlPage
qm.test.web.web.DirPage
qm.test.web.web.DirReportPage
qm.test.web.web.Item
qm.test.web.web.LoadContextPage
qm.test.web.web.LoadExpectationsPage
qm.test.web.web.LoadResultsPage
qm.test.web.web.NewItemPage
qm.test.web.web.NewSuitePage
qm.test.web.web.QMTestPage
qm.test.web.web.QMTestReportPage
qm.test.web.web.QMTestServer
qm.test.web.web.ResultPage
qm.test.web.web.SetExpectationPage
qm.test.web.web.ShowItemPage
qm.test.web.web.ShowItemReportPage
qm.test.web.web.ShowSuitePage
qm.test.web.web.StorageResultsStream
qm.test.web.web.TestResultsPage
qm.trace.Tracer
qm.user.AccountDisabledError
qm.user.AuthenticationError
qm.user.Authenticator
qm.user.DefaultAuthenticator
qm.user.DefaultDatabase
qm.user.Group
qm.user.User
qm.user.XmlDatabase
qm.user.XmlDatabaseAuthenticator
qm.user.XmlDatabaseError
qm.web.AddressInUseError
qm.web.CGIWebRequest
qm.web.DtmlPage
qm.web.HTTPServer
qm.web.HttpRedirect
qm.web.InvalidSessionError
qm.web.NoSessionError
qm.web.PrivilegedPortError
qm.web.Session
qm.web.WebRequest
qm.web.WebRequestHandler
qm.web.WebServer
random.Random
random.SystemRandom
random.WichmannHill
str
string.Template
string._TemplateMetaclass
string._multimap

All Functions

qm.attachment.from_dom_node
qm.attachment.make_dom_node
qm.attachment.make_temporary_location
qm.common.close_file_on_exec
qm.common.convert_from_dos_text
qm.common.copy
qm.common.format_exception
qm.common.format_time
qm.common.format_time_iso
qm.common.format_traceback
qm.common.get_doc_directory
qm.common.get_lib_directory
qm.common.get_share_directory
qm.common.get_userid
qm.common.get_username
qm.common.html_to_text
qm.common.load_class
qm.common.load_module
qm.common.make_unique_tag
qm.common.open_temporary_file
qm.common.open_temporary_file_fd
qm.common.parse_assignment
qm.common.parse_boolean
qm.common.parse_string_list
qm.common.parse_time
qm.common.parse_time_iso
qm.common.read_assignments
qm.common.split_argument_list
qm.common.split_path_fully
qm.common.wrap_lines
qm.db.quote_string
qm.diagnostic.error
qm.diagnostic.get_diagnostic_set
qm.diagnostic.get_help_set
qm.diagnostic.load_messages
qm.diagnostic.message
qm.diagnostic.warning
qm.external.DocumentTemplate.DT_In.basic_type
qm.external.DocumentTemplate.DT_In.int_param
qm.external.DocumentTemplate.DT_InSV.opt
qm.external.DocumentTemplate.DT_InSV.sub
qm.external.DocumentTemplate.DT_Let.parse_let_params
qm.external.DocumentTemplate.DT_Util.careful_getattr
qm.external.DocumentTemplate.DT_Util.careful_getitem
qm.external.DocumentTemplate.DT_Util.careful_getslice
qm.external.DocumentTemplate.DT_Util.careful_hasattr
qm.external.DocumentTemplate.DT_Util.careful_pow
qm.external.DocumentTemplate.DT_Util.careful_range
qm.external.DocumentTemplate.DT_Util.html_quote
qm.external.DocumentTemplate.DT_Util.int_param
qm.external.DocumentTemplate.DT_Util.name_param
qm.external.DocumentTemplate.DT_Util.namespace
qm.external.DocumentTemplate.DT_Util.obsolete_attr
qm.external.DocumentTemplate.DT_Util.parse_params
qm.external.DocumentTemplate.DT_Util.render
qm.external.DocumentTemplate.DT_Util.test
qm.external.DocumentTemplate.DT_Var.dollars_and_cents
qm.external.DocumentTemplate.DT_Var.dollars_and_cents_with_commas
qm.external.DocumentTemplate.DT_Var.len_comma
qm.external.DocumentTemplate.DT_Var.len_format
qm.external.DocumentTemplate.DT_Var.newline_to_br
qm.external.DocumentTemplate.DT_Var.spacify
qm.external.DocumentTemplate.DT_Var.sql_quote
qm.external.DocumentTemplate.DT_Var.structured_text
qm.external.DocumentTemplate.DT_Var.thousands_commas
qm.external.DocumentTemplate.DT_Var.url_quote
qm.external.DocumentTemplate.DT_Var.url_quote_plus
qm.external.DocumentTemplate.DT_Var.url_unquote
qm.external.DocumentTemplate.DT_Var.url_unquote_plus
qm.external.DocumentTemplate.DT_Var.whole_dollars
qm.external.DocumentTemplate.DT_Var.whole_dollars_with_commas
qm.external.DocumentTemplate.DTtestExpr.test1
qm.external.DocumentTemplate.DTtestExpr.test2
qm.external.DocumentTemplate.DTtestExpr.test3
qm.external.DocumentTemplate.DTtestExpr.test4
qm.external.DocumentTemplate.VSEval.careful_mul
qm.external.DocumentTemplate.VSEval.default_slicer
qm.external.DocumentTemplate.gparse.compile
qm.external.DocumentTemplate.gparse.dot_munge
qm.external.DocumentTemplate.gparse.item_munge
qm.external.DocumentTemplate.gparse.multi_munge
qm.external.DocumentTemplate.gparse.munge
qm.external.DocumentTemplate.gparse.slice_munge
qm.external.DocumentTemplate.pDocumentTemplate.isFunctionType
qm.external.DocumentTemplate.pDocumentTemplate.isSimpleType
qm.external.DocumentTemplate.pDocumentTemplate.render_blocks
qm.label.thunk
qm.platform.get_shell_for_command
qm.platform.get_shell_for_script
qm.platform_unix.get_host_name
qm.platform_unix.get_signal_name
qm.platform_unix.install_signal_handler
qm.platform_unix.open_in_browser
qm.platform_win32.get_host_name
qm.platform_win32.open_in_browser
qm.setup.find_packages_r
qm.structured_text.escape_html_entities
qm.structured_text.get_first
qm.structured_text.get_first_paragraph
qm.structured_text.get_paragraphs
qm.structured_text.get_rest
qm.structured_text.to_html
qm.structured_text.to_text
qm.test.base.get_extension_class
qm.test.base.get_extension_class_from_directory
qm.test.base.get_extension_class_names
qm.test.base.get_extension_class_names_in_directory
qm.test.base.get_extension_classes
qm.test.base.get_extension_directories
qm.test.base.get_resource_class
qm.test.base.get_test_class
qm.test.base.load_expectations
qm.test.base.load_outcomes
qm.test.base.load_results
qm.test.classes.python.make_namespaces
qm.test.cmdline.get_qmtest
qm.test.test.get_targets
qm.test.test.set_targets
qm.web.decode_properties
qm.web.decode_set_control_contents
qm.web.encode_properties
qm.web.encode_set_control_contents
qm.web.escape
qm.web.format_color
qm.web.format_exception
qm.web.format_structured_text
qm.web.generate_error_page
qm.web.generate_login_form
qm.web.get_session
qm.web.handle_login
qm.web.handle_logout
qm.web.http_return_exception
qm.web.http_return_html
qm.web.javascript_escape
qm.web.javascript_unescape
qm.web.make_button_for_popup
qm.web.make_button_for_request
qm.web.make_button_for_url
qm.web.make_choose_control
qm.web.make_help_link
qm.web.make_help_link_html
qm.web.make_javascript_string
qm.web.make_popup_page
qm.web.make_properties_control
qm.web.make_set_control
qm.web.make_submit_button
qm.web.make_url
qm.web.parse_url_query
qm.web.unescape

All Variables

math.e
math.pi
qm.common.program_name
qm.common.rc
qm.config.data_dir
qm.config.doc_dir
qm.config.extension_path
qm.config.version
qm.external.DocumentTemplate.DT_If.__doc__
qm.external.DocumentTemplate.DT_If.__rcs_id__
qm.external.DocumentTemplate.DT_In.In
qm.external.DocumentTemplate.DT_In.__rcs_id__
qm.external.DocumentTemplate.DT_InSV.__doc__
qm.external.DocumentTemplate.DT_InSV.mv
qm.external.DocumentTemplate.DT_Raise.__rcs_id__
qm.external.DocumentTemplate.DT_UI.FactoryDefaultString
qm.external.DocumentTemplate.DT_UI.__doc__
qm.external.DocumentTemplate.DT_Util.Expr_doc
qm.external.DocumentTemplate.DT_Util.ParseError
qm.external.DocumentTemplate.DT_Util.ValidationError
qm.external.DocumentTemplate.DT_Util.d
qm.external.DocumentTemplate.DT_Util.expr_globals
qm.external.DocumentTemplate.DT_Util.name
qm.external.DocumentTemplate.DT_Var.StructuredText
qm.external.DocumentTemplate.DT_Var.__doc__
qm.external.DocumentTemplate.DT_Var.__rcs_id__
qm.external.DocumentTemplate.DT_Var.modifiers
qm.external.DocumentTemplate.DT_Var.special_formats
qm.external.DocumentTemplate.DT_With.__rcs_id__
qm.external.DocumentTemplate.DTtestExpr.__doc__
qm.external.DocumentTemplate.DocumentTemplate.ParseError
qm.external.DocumentTemplate.VSEval.__rcs_id__
qm.external.DocumentTemplate.VSEval.compiled_getattr
qm.external.DocumentTemplate.VSEval.default_globals
qm.external.DocumentTemplate.VSEval.gparse
qm.external.DocumentTemplate.VSEval.nltosp
qm.external.DocumentTemplate.__doc__
qm.external.DocumentTemplate.gparse.ParseError
qm.external.DocumentTemplate.pDocumentTemplate.n
qm.external.DocumentTemplate.pDocumentTemplate.name
qm.platform_unix.default_shell
qm.platform_win32.default_shell
qm.prefix
qm.setup.packages
qm.structured_text.character
qm.structured_text.entity
qm.structured_text.html_help_text
qm.test.base.extension_kinds
qm.user.authenticator
qm.user.database
qm.user.xml_user_database_dtd
qm.version_info
qm.web.session_id_field
qm.web.sessions
random.BPF
random.LOG4
random.NV_MAGICCONST
random.RECIP_BPF
random.SG_MAGICCONST
random.TWOPI
random._e
random._inst
random._pi
string._idmap
string._idmapL
string.ascii_letters
string.ascii_lowercase
string.ascii_uppercase
string.digits
string.hexdigits
string.letters
string.lowercase
string.octdigits
string.printable
string.punctuation
string.uppercase
string.whitespace

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python-module.html0000664000076400007640000002113311122067145026513 0ustar stefanstefan qm.test.classes.python
Package qm :: Package test :: Package classes :: Module python
[hide private]
[frames] | no frames]

Module python

source code

Test classes for tests written in Python.

Classes [hide private]
  ExecTest
Check that a Python expression evaluates to true.
  BaseExceptionTest
Base class for tests of exceptions.
  ExceptionTest
Check that the specified Python code raises an exception.
  StringExceptionTest
Check that the specified Python code raises a string exception.
Functions [hide private]
 
make_namespaces(context)
Construct namespaces for eval/exec of Python test code.
source code
Function Details [hide private]

make_namespaces(context)

source code 

Construct namespaces for eval/exec of Python test code.

'context' -- The test context.

returns -- A pair '(global_namespace, local_namespace)' of maps.


qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-V.html0000664000076400007640000002705511122067144024323 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

V



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command-pysrc.html0000664000076400007640000051447411122067154026502 0ustar stefanstefan qm.test.classes.command
Package qm :: Package test :: Package classes :: Module command
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.command

  1  ######################################################################## 
  2  # 
  3  # File:   command.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-03-24 
  6  # 
  7  # Contents: 
  8  #   Test classes for testing command-line programs. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import cPickle 
 21  import errno 
 22  import os 
 23  import qm.common 
 24  import qm.executable 
 25  import qm.fields 
 26  import qm.test.base 
 27  from   qm.test.test import Test 
 28  from   qm.test.result import Result 
 29  import string 
 30  import sys 
 31  import types 
 32   
 33  ######################################################################## 
 34  # Classes 
 35  ######################################################################## 
 36   
37 -class ExecTestBase(Test):
38 """Check a program's output and exit code. 39 40 An 'ExecTestBase' runs a program and compares its standard output, 41 standard error, and exit code with expected values. The program 42 may be provided with command-line arguments and/or standard 43 input. 44 45 The test passes if the standard output, standard error, and 46 exit code are identical to the expected values.""" 47 48 arguments = [ 49 qm.fields.TextField( 50 name="stdin", 51 title="Standard Input", 52 verbatim="true", 53 multiline="true", 54 description="""The contents of the standard input stream. 55 56 If this field is left blank, the standard input stream will 57 contain no data.""" 58 ), 59 60 qm.fields.SetField(qm.fields.TextField( 61 name="environment", 62 title="Environment", 63 description="""Additional environment variables. 64 65 By default, QMTest runs tests with the same environment that 66 QMTest is running in. If you run tests in parallel, or 67 using a remote machine, the environment variables available 68 will be dependent on the context in which the remote test 69 is executing. 70 71 You may add variables to the environment. Each entry must 72 be of the form 'VAR=VAL'. The program will be run in an 73 environment where the environment variable 'VAR' has the 74 value 'VAL'. If 'VAR' already had a value in the 75 environment, it will be replaced with 'VAL'. 76 77 In addition, QMTest automatically adds an environment 78 variable corresponding to each context property. The name 79 of the environment variable is the name of the context 80 property, prefixed with 'QMV_'. For example, if the value 81 of the context property named 'target' is available in the 82 environment variable 'QMV_target'. Any dots in the context 83 key are replaced by a double-underscore; e.g., 84 "CompilerTable.c_path" will become 85 "QMV_CompilerTable__c_path".""" )), 86 87 qm.fields.IntegerField( 88 name="exit_code", 89 title="Exit Code", 90 description="""The expected exit code. 91 92 Most programs use a zero exit code to indicate success and a 93 non-zero exit code to indicate failure.""" 94 ), 95 96 qm.fields.TextField( 97 name="stdout", 98 title="Standard Output", 99 verbatim="true", 100 multiline="true", 101 description="""The expected contents of the standard output stream. 102 103 If the output written by the program does not match this 104 value, the test will fail.""" 105 ), 106 107 qm.fields.TextField( 108 name="stderr", 109 title="Standard Error", 110 verbatim="true", 111 multiline="true", 112 description="""The expected contents of the standard error stream. 113 114 If the output written by the program does not match this 115 value, the test will fail.""" 116 ), 117 118 qm.fields.IntegerField( 119 name="timeout", 120 title="Timeout", 121 description="""The number of seconds the child program will run. 122 123 If this field is non-negative, it indicates the number of 124 seconds the child program will be permitted to run. If this 125 field is not present, or negative, the child program will be 126 permitted to run for ever.""", 127 default_value = -1, 128 ), 129 ] 130 131
132 - def MakeEnvironment(self, context):
133 """Construct the environment for executing the target program.""" 134 135 # Start with any environment variables that are already present 136 # in the environment. 137 environment = os.environ.copy() 138 # Copy context variables into the environment. 139 for key, value in context.items(): 140 # If the value has unicode type, only transfer 141 # it if it can be cast to str. 142 if isinstance(value, unicode): 143 try: 144 value = str(value) 145 except UnicodeEncodeError: 146 continue 147 if isinstance(value, str): 148 name = "QMV_" + key.replace(".", "__") 149 environment[name] = value 150 # Extract additional environment variable assignments from the 151 # 'Environment' field. 152 for assignment in self.environment: 153 if "=" in assignment: 154 # Break the assignment at the first equals sign. 155 variable, value = string.split(assignment, "=", 1) 156 environment[variable] = value 157 else: 158 raise ValueError, \ 159 qm.error("invalid environment assignment", 160 assignment=assignment) 161 return environment
162 163
164 - def ValidateOutput(self, stdout, stderr, result):
165 """Validate the output of the program. 166 167 'stdout' -- A string containing the data written to the standard output 168 stream. 169 170 'stderr' -- A string containing the data written to the standard error 171 stream. 172 173 'result' -- A 'Result' object. It may be used to annotate 174 the outcome according to the content of stderr. 175 176 returns -- A list of strings giving causes of failure.""" 177 178 causes = [] 179 # Check to see if the standard output matches. 180 if not self.__CompareText(stdout, self.stdout): 181 causes.append("standard output") 182 result["ExecTest.expected_stdout"] = result.Quote(self.stdout) 183 # Check to see if the standard error matches. 184 if not self.__CompareText(stderr, self.stderr): 185 causes.append("standard error") 186 result["ExecTest.expected_stderr"] = result.Quote(self.stderr) 187 188 return causes
189 190
191 - def RunProgram(self, program, arguments, context, result):
192 """Run the 'program'. 193 194 'program' -- The path to the program to run. 195 196 'arguments' -- A list of the arguments to the program. This 197 list must contain a first argument corresponding to 'argv[0]'. 198 199 'context' -- A 'Context' giving run-time parameters to the 200 test. 201 202 'result' -- A 'Result' object. The outcome will be 203 'Result.PASS' when this method is called. The 'result' may be 204 modified by this method to indicate outcomes other than 205 'Result.PASS' or to add annotations.""" 206 207 # Construct the environment. 208 environment = self.MakeEnvironment(context) 209 # Create the executable. 210 if self.timeout >= 0: 211 timeout = self.timeout 212 else: 213 # If no timeout was specified, we sill run this process in a 214 # separate process group and kill the entire process group 215 # when the child is done executing. That means that 216 # orphaned child processes created by the test will be 217 # cleaned up. 218 timeout = -2 219 e = qm.executable.Filter(self.stdin, timeout) 220 # Run it. 221 status = e.Run(arguments, environment, path = program) 222 223 causes = [] 224 # Validate the exit status. 225 if not result.CheckExitStatus('ExecTest.', 'Program', 226 status, self.exit_code): 227 causes.append("exit_code") 228 result["ExecTest.expected_exit_code"] = str(self.exit_code) 229 230 result["ExecTest.stdout"] = result.Quote(e.stdout) 231 result["ExecTest.stderr"] = result.Quote(e.stderr) 232 233 # Validate the output. 234 causes += self.ValidateOutput(e.stdout, e.stderr, result) 235 # If anything went wrong, the test failed. 236 if causes: 237 result.Fail("Unexpected %s." % string.join(causes, ", "))
238 239
240 - def __CompareText(self, s1, s2):
241 """Compare 's1' and 's2', ignoring line endings. 242 243 's1' -- A string. 244 245 's2' -- A string. 246 247 returns -- True if 's1' and 's2' are the same, ignoring 248 differences in line endings.""" 249 250 # The "splitlines" method works independently of the line ending 251 # convention in use. 252 return s1.splitlines() == s2.splitlines()
253 254
255 -class ExecTest(ExecTestBase):
256 """Check a program's output and exit code. 257 258 An 'ExecTest' runs a program by using the 'exec' system call.""" 259 260 arguments = [ 261 qm.fields.TextField( 262 name="program", 263 title="Program", 264 not_empty_text=1, 265 description="""The path to the program. 266 267 This field indicates the path to the program. If it is not 268 an absolute path, the value of the 'PATH' environment 269 variable will be used to search for the program.""" 270 ), 271 272 qm.fields.SetField(qm.fields.TextField( 273 name="arguments", 274 title="Argument List", 275 description="""The command-line arguments. 276 277 If this field is left blank, the program is run without any 278 arguments. 279 280 An implicit 0th argument (the path to the program) is added 281 automatically.""" 282 ))] 283 284 _allow_arg_names_matching_class_vars = 1 285 286
287 - def Run(self, context, result):
288 """Run the test. 289 290 'context' -- A 'Context' giving run-time parameters to the 291 test. 292 293 'result' -- A 'Result' object. The outcome will be 294 'Result.PASS' when this method is called. The 'result' may be 295 modified by this method to indicate outcomes other than 296 'Result.PASS' or to add annotations.""" 297 298 # Was the program not specified? 299 if string.strip(self.program) == "": 300 result.Fail("No program specified.") 301 return 302 303 self.RunProgram(self.program, 304 [ self.program ] + self.arguments, 305 context, result)
306 307 308
309 -class ShellCommandTest(ExecTestBase):
310 """Check a shell command's output and exit code. 311 312 A 'ShellCommandTest' runs the shell and compares its standard 313 output, standard error, and exit code with expected values. The 314 shell may be provided with command-line arguments and/or standard 315 input. 316 317 QMTest determines which shell to use by the following method: 318 319 - If the context contains the property 320 'ShellCommandTest.command_shell', its value is split into 321 an argument list and used. 322 323 - Otherwise, if the '.qmrc' configuration file contains the common 324 property 'command_shell', its value is split into an argument 325 list and used. 326 327 - Otherwise, the default shell for the target system is used. 328 329 """ 330 331 arguments = [ 332 qm.fields.TextField( 333 name="command", 334 title="Command", 335 description="""The arguments to the shell. 336 337 This field contains the arguments that are passed to the 338 shell. It should not contain the path to the shell itself. 339 340 If this field is left blank, the shell is run without 341 arguments.""" 342 ) 343 ] 344 345
346 - def Run(self, context, result):
347 """Run the test. 348 349 'context' -- A 'Context' giving run-time parameters to the 350 test. 351 352 'result' -- A 'Result' object. The outcome will be 353 'Result.PASS' when this method is called. The 'result' may be 354 modified by this method to indicate outcomes other than 355 'Result.PASS' or to add annotations.""" 356 357 # If the context specifies a shell, use it. 358 if context.has_key("ShellCommandTest.command_shell"): 359 # Split the context value to build the argument list. 360 shell = qm.common.split_argument_list( 361 context["ShellCommandTest.command_shell"]) 362 else: 363 # Otherwise, use a platform-specific default. 364 shell = qm.platform.get_shell_for_command() 365 # Append the command at the end of the argument list. 366 arguments = shell + [ self.command ] 367 self.RunProgram(arguments[0], arguments, context, result)
368 369 370
371 -class ShellScriptTest(ExecTestBase):
372 """Check a shell script's output and exit code. 373 374 A 'ShellScriptTest' runs the shell script provided and compares its 375 standard output, standard error, and exit code with expected values. 376 The shell script may be provided with command-line arguments and/or 377 standard input. 378 379 QMTest determines which shell to use by the following method: 380 381 - If the context contains the property 382 'ShellScriptTest.script_shell', its value is split into an 383 argument list and used. 384 385 - Otherwise, if the '.qmrc' configuration file contains the common 386 property 'script_shell', its value is split into an argument 387 list and used. 388 389 - Otherwise, the default shell for the target system is used. 390 391 """ 392 393 arguments = [ 394 qm.fields.TextField( 395 name="script", 396 title="Script", 397 description="""The contents of the shell script. 398 399 Provide the entire shell script here. The script will be 400 written to a temporary file before it is executed. There 401 does not need to be an explicit '#! /path/to/shell' at 402 the beginning of the script because QMTest will not directly 403 invoke the script. Instead, it will run the shell, passing 404 it the name of the temporary file containing the script as 405 an argument.""", 406 verbatim="true", 407 multiline="true", 408 ), 409 qm.fields.SetField(qm.fields.TextField( 410 name="arguments", 411 title="Argument List", 412 description="""The command-line arguments. 413 414 If this field is left blank, the program is run without any 415 arguments. 416 417 An implicit 0th argument (the path to the program) is added 418 automatically.""" 419 )) 420 ] 421 422 _allow_arg_names_matching_class_vars = 1 423 424
425 - def Run(self, context, result):
426 """Run the test. 427 428 'context' -- A 'Context' giving run-time parameters to the 429 test. 430 431 'result' -- A 'Result' object. The outcome will be 432 'Result.PASS' when this method is called. The 'result' may be 433 modified by this method to indicate outcomes other than 434 'Result.PASS' or to add annotations.""" 435 436 # On Windows, batch files must end with a ".bat" suffix or the 437 # command shell will not execute them. 438 if sys.platform == "win32": 439 suffix = ".bat" 440 else: 441 suffix = "" 442 # Create a temporary file for the script. 443 self.__script_file_name, script_file \ 444 = qm.open_temporary_file("w+", suffix) 445 try: 446 # Write the script to the temporary file. 447 script_file.write(self.script) 448 script_file.close() 449 shell = self._GetShell(context) 450 # Construct the argument list. The argument list for the 451 # interpreter is followed by the name of the script 452 # temporary file, and then the arguments to the script. 453 arguments = shell \ 454 + [ self.__script_file_name ] \ 455 + self.arguments 456 self.RunProgram(arguments[0], arguments, context, result) 457 finally: 458 # Clean up the script file. 459 os.remove(self.__script_file_name)
460 461
462 - def _GetShell(self, context):
463 """Return the shell to use to run this test. 464 465 'context' -- As for 'Test.Run'. 466 467 returns -- A sequence of strings giving the path and arguments 468 to be supplied to the shell. The default implementation uses 469 the value of the context property 470 'ShellScriptTest.script_shell', or, if that is not defined, a 471 platform-specific default.""" 472 473 # If the context specifies a shell, use it. 474 if context.has_key("ShellScriptTest.script_shell"): 475 # Split the context value to build the argument list. 476 return qm.common.split_argument_list( 477 context["ShellScriptTest.script_shell"]) 478 479 # Otherwise, use a platform-specific default. 480 return qm.platform.get_shell_for_script()
481 482 483 484 ######################################################################## 485 # Local Variables: 486 # mode: python 487 # indent-tabs-mode: nil 488 # fill-column: 72 489 # End: 490

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dg_test-module.html0000664000076400007640000001122711122067145026626 0ustar stefanstefan qm.test.classes.dg_test
Package qm :: Package test :: Package classes :: Module dg_test
[hide private]
[frames] | no frames]

Module dg_test

source code

Classes [hide private]
  DGTest
A 'DGTest' is a test using the DejaGNU 'dg' driver.
././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate.TemplateDic0000664000076400007640000010645511122067146033264 0ustar stefanstefan qm.external.DocumentTemplate.pDocumentTemplate.TemplateDict
Package qm :: Package external :: Package DocumentTemplate :: Module pDocumentTemplate :: Class TemplateDict
[hide private]
[frames] | no frames]

Class TemplateDict

source code

Nested Classes [hide private]
  float
float(x) -> floating point number
  int
int(x[, base]) -> integer
  str
str(object) -> string
Instance Methods [hide private]
 
_pop(self, n=1) source code
 
_push(self, d) source code
 
__init__(self) source code
 
__getitem__(self, key, call=1, simple=<built-in method has_key of dict object at 0x7f00bca50630>, isFunctionType=<built-in method has_key of dict object at 0x7f00bca50a80>) source code
 
has_key(self, key) source code
 
getitem(self, key, call=1, simple=<built-in method has_key of dict object at 0x7f00bca50630>, isFunctionType=<built-in method has_key of dict object at 0x7f00bca50a80>) source code
 
__call__(self, *args, **kw) source code
number
abs(number)
Return the absolute value of the argument.
 
attr(self, inst, name, md) source code
character
chr(i)
Return a string of one character with ordinal i; 0 <= i < 256.
(div, mod)
divmod(x, y)
Return the tuple ((x-x%y)/y, x%y).
 
getattr(md, inst, name, default=[]) source code
 
hasattr(md, inst, name) source code
integer
hash(object)
Return a hash value for the object.
string
hex(number)
Return the hexadecimal representation of an integer or long integer.
integer
len(object)
Return the number of items of a sequence or mapping.
value
max(iterable, key=func)
max(a, b, c, ...[, key=func]) -> value
value
min(iterable, key=func)
min(a, b, c, ...[, key=func]) -> value
 
namespace(self, **kw)
Create a tuple consisting of a single instance whose attributes are provided as keyword arguments.
source code
string
oct(number)
Return the octal representation of an integer or long integer.
integer
ord(c)
Return the integer ordinal of a one-character string.
 
pow(self, x, y, z) source code
 
range(md, iFirst, *args) source code
 
render(self, v)
Render an object in the way done by the 'name' attribute
source code
floating point number
round(number, ndigits=...)
Round a number to a given precision in decimal digits (default 0 digits).
 
test(self, *args) source code
Class Variables [hide private]
  level = 0
  None = None
  math
This module is always available.
  random
Random variable generators.
  string
A collection of string operations (most are no longer used).
Method Details [hide private]

divmod(x, y)

 

Return the tuple ((x-x%y)/y, x%y). Invariant: div*y + mod == x.

Returns: (div, mod)

hash(object)

 

Return a hash value for the object. Two objects with the same value have the same hash value. The reverse is not necessarily true, but likely.

Returns: integer

max(iterable, key=func)

 

max(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its largest item. With two or more arguments, return the largest argument.

Returns: value

min(iterable, key=func)

 

min(a, b, c, ...[, key=func]) -> value

With a single iterable argument, return its smallest item. With two or more arguments, return the smallest argument.

Returns: value

round(number, ndigits=...)

 

Round a number to a given precision in decimal digits (default 0 digits). This always returns a floating point number. Precision may be negative.

Returns: floating point number

Class Variable Details [hide private]

math

This module is always available. It provides access to the mathematical functions defined by the C standard.

Value:
math

random

Random variable generators.

    integers
    --------
           uniform within range

    sequences
    ---------
           pick random element
           pick random sample
           generate random permutation

    distributions on the real line:
    ------------------------------
           uniform
           normal (Gaussian)
           lognormal
           negative exponential
           gamma
           beta
           pareto
           Weibull

    distributions on the circle (angles 0 to 2pi)
    ---------------------------------------------
           circular uniform
           von Mises

General notes on the underlying Mersenne Twister core generator:

* The period is 2**19937-1.
* It is one of the most extensively tested generators in existence.
* Without a direct way to compute N steps forward, the semantics of
  jumpahead(n) are weakened to simply jump to another distant state and rely
  on the large period to avoid overlapping sequences.
* The random() method is implemented in C, executes in a single Python step,
  and is, therefore, threadsafe.

Value:
random

string

A collection of string operations (most are no longer used).

Warning: most of the code you see here isn't normally used nowadays. Beginning with Python 1.6, many of these functions are implemented as methods on the standard string object. They used to be implemented by a built-in module called strop, but strop is now obsolete itself.

Public module variables:

whitespace -- a string containing all characters considered whitespace lowercase -- a string containing all characters considered lowercase letters uppercase -- a string containing all characters considered uppercase letters letters -- a string containing all characters considered letters digits -- a string containing all characters considered decimal digits hexdigits -- a string containing all characters considered hexadecimal digits octdigits -- a string containing all characters considered octal digits punctuation -- a string containing all characters considered punctuation printable -- a string containing all characters considered printable

Value:
string

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.setup-pysrc.html0000664000076400007640000005246311122067153023604 0ustar stefanstefan qm.setup
Package qm :: Module setup
[hide private]
[frames] | no frames]

Source Code for Module qm.setup

 1  ######################################################################## 
 2  # 
 3  # File:   setup.py 
 4  # Author: Mark Mitchell 
 5  # Date:   01/02/2002 
 6  # 
 7  # Contents: 
 8  #   QM Distutils setup script. 
 9  # 
10  # Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ######################################################################## 
17   
18  from   distutils.core import setup 
19  import os 
20  import os.path 
21  import string 
22   
23  ######################################################################## 
24  # Functions 
25  ######################################################################## 
26   
27 -def find_packages_r(packages, dirname, names):
28 """If 'dirname' is a QM package, add it to 'packages'. 29 30 'packages' -- A mutable sequence of package names. 31 32 'dirname' -- The (relative) path from the base of the QM package 33 to the directory. 34 35 'names' -- A mutable sequence of file names indicating files (and 36 directories) contained in the directory given by 'dirname'.""" 37 38 # If the directory contains a file called __init__.py, it is a 39 # package. Directories named "classes" contain extension classes. 40 if "__init__.py" in names or os.path.basename(dirname) == "classes": 41 # Replace a leading "." with "qm". 42 d = "qm" + dirname[1:] 43 # Replace path separators with periods. 44 d = string.replace(d, os.sep, ".") 45 if os.altsep: 46 d = string.replace(d, os.altsep, ".") 47 packages.append(d) 48 # Exclude directories named "build"; they are created by Distutils. 49 if "build" in names: 50 names.remove("build")
51 52 ######################################################################## 53 # Main Program 54 ######################################################################## 55 56 # Find all of the packages that make up QM. 57 packages = [] 58 os.path.walk(".", find_packages_r, packages) 59 60 setup(name="qm", 61 version="1.1", 62 packages=packages, 63 package_dir={ 'qm' : '.' }) 64

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.attachment.Attachment-class.html0000664000076400007640000004371311122067145026627 0ustar stefanstefan qm.attachment.Attachment
Package qm :: Module attachment :: Class Attachment
[hide private]
[frames] | no frames]

Class Attachment

source code

An arbitrary file attachment.

Conceptually, an attachment is composed of these parts:

  1. A MIME type, as a string.
  2. A description, as a structured text string.
  3. A file name, corresponding to the original name of the file from which the attachment was uploaded, or the name of the file to use when the attachment is presented to the user in a file system.
  4. A block of arbitrary data.

For efficiency reasons, the attachment data is not stored in the attachment. Instead, a *location* is stored, which is a key into the associated 'AttachmentStore' object.

Instance Methods [hide private]
 
__init__(self, mime_type, description, file_name, location, store)
Create a new attachment.
source code
 
GetMimeType(self)
Return the attachment's MIME type.
source code
 
GetDescription(self)
Return the attachment's description.
source code
 
GetFileName(self)
Return the attachment's file name.
source code
 
GetLocation(self)
Return the attachment's location in an attachment store.
source code
 
GetData(self)
Get attachment data.
source code
 
GetDataFile(self)
Return the path to a file containing attachment data.
source code
 
GetStore(self)
Return the store in which this attachment is located.
source code
 
Move(self, store, location)
Move the 'Attachment' to a new location.
source code
 
__str__(self) source code
 
__cmp__(self, other) source code
Method Details [hide private]

__init__(self, mime_type, description, file_name, location, store)
(Constructor)

source code 

Create a new attachment.

'mime_type' -- The MIME type. If 'None' or an empty string, the function attempts to guess the MIME type from other information.

'description' -- A description of the attachment contents.

'file_name' -- The user-visible file name to associate the attachment.

'location' -- The location in an attachment store at which to find the attachment data.

'store' -- The attachment store in which the data is stored.

GetData(self)

source code 

Get attachment data.

returns -- The attachment data.

GetDataFile(self)

source code 

Return the path to a file containing attachment data.

returns -- A file system path. The file should be considered read-only, and should not be modified in any way.

GetStore(self)

source code 

Return the store in which this attachment is located.

returns -- The 'AttachmentStore' that contains this attachment.

Move(self, store, location)

source code 

Move the 'Attachment' to a new location.

'store' -- The 'AttachmentStore' that will contain the attachment.

'location' -- The location of the attachment within its current store.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.ResourceDescriptor-class.html0000664000076400007640000003514411122067150030752 0ustar stefanstefan qm.test.database.ResourceDescriptor
qm :: test :: database :: ResourceDescriptor :: Class ResourceDescriptor
[hide private]
[frames] | no frames]

Class ResourceDescriptor

source code

ItemDescriptor --+
                 |
                ResourceDescriptor

A resource instance.

Instance Methods [hide private]
 
__init__(self, database, resource_id, resource_class_name=None, arguments=None, resource=None)
Create a new resource instance.
source code
 
GetClass(self)
Return the class of the entity.
source code
 
GetResource(self)
Return the 'Resource' object described by this descriptor.
source code
 
SetUp(self, context, result)
Set up the resource.
source code
 
CleanUp(self, result)
Clean up the resource.
source code

Inherited from ItemDescriptor: GetArguments, GetClassArguments, GetClassName, GetDatabase, GetId, GetItem, GetResources

Inherited from ItemDescriptor (private): _Execute

Method Details [hide private]

__init__(self, database, resource_id, resource_class_name=None, arguments=None, resource=None)
(Constructor)

source code 

Create a new resource instance.

'database' -- The 'Database' containing this resource.

'resource_id' -- The resource ID.

'resource_class_name' -- The name of the resource class of which this is an instance. Omit this argument if 'resource' is provided.

'arguments' -- This resource's arguments to the resource class. Omit this argument if 'resource' is provided.

'resource' -- The resource class of which this is an instance.

Overrides: ItemDescriptor.__init__

GetClass(self)

source code 

Return the class of the entity.

returns -- The Python class object for the entity. For example, for a 'TestDescriptor', this method returns the test class.

Overrides: ItemDescriptor.GetClass

SetUp(self, context, result)

source code 

Set up the resource.

'context' -- The 'Context' in which the resource should be executed.

'result' -- The 'Result' object for this resource.

CleanUp(self, result)

source code 

Clean up the resource.

'result' -- The 'Result' object for this resource.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.QMTestPage-class.html0000664000076400007640000005300611122067151026661 0ustar stefanstefan qm.test.web.web.QMTestPage
Package qm :: Package test :: Package web :: Module web :: Class QMTestPage
[hide private]
[frames] | no frames]

Class QMTestPage

source code

web.DtmlPage --+    
               |    
 DefaultDtmlPage --+
                   |
                  QMTestPage

A 'QMTestPage' is a 'DtmlPage' for pages generated by QMTest.

A 'QMTestPage' automatically looks for DTML templates in the directory that contains QMTest DTML templates.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, dtml_template, server)
Construct a new 'QMTestPage'.
source code
 
GenerateStartBody(self, decorations=1)
Return markup to start the body of the HTML document.
source code
 
IsFinished(self)
Return true iff no more results are forthcoming.
source code
 
GetRefreshDelay(self)
Returns the number of seconds to wait before refreshing the page.
source code
 
GenerateHtmlHeader(self, description, headers="")
Return the header for an HTML document.
source code
 
GetExpectationUrl(self, id, expectation)
Return the URL for setting the expectation associated with 'id'.
source code

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, dtml_template, server)
(Constructor)

source code 

Construct a new 'QMTestPage'.

'dtml_template' -- The file name of the DTML template, relative to the directory that contains QMTest DTML templates. (Usually, this is just a basename.)

'server' -- The 'QMTestServer' creating this page.

Overrides: web.DtmlPage.__init__

GenerateStartBody(self, decorations=1)

source code 

Return markup to start the body of the HTML document.

Overrides: web.DtmlPage.GenerateStartBody
(inherited documentation)

IsFinished(self)

source code 

Return true iff no more results are forthcoming.

returns -- True if no more tests are running.

GetRefreshDelay(self)

source code 

Returns the number of seconds to wait before refreshing the page.

returns -- The number of seconds to wait before refreshing this page. A value of zero means that te page should never be refreshed. This function is only called if 'IsFinished' returns true.

GenerateHtmlHeader(self, description, headers="")

source code 

Return the header for an HTML document.

'description' -- A string describing this page.

'headers' -- Any additional HTML headers to place in the '<head>' section of the HTML document.

Overrides: web.DtmlPage.GenerateHtmlHeader

GetExpectationUrl(self, id, expectation)

source code 

Return the URL for setting the expectation associated with 'id'.

'id' -- The name of a test.

'expectation' -- The current expectation associated with the test, or 'None' if there is no associated expectation.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test-pysrc.html0000664000076400007640000026446211122067157030443 0ustar stefanstefan qm.test.classes.compilation_test
Package qm :: Package test :: Package classes :: Module compilation_test
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.compilation_test

  1  ######################################################################## 
  2  # 
  3  # File:   compilation_test.py 
  4  # Author: Stefan Seefeld 
  5  # Date:   2005-10-17 
  6  # 
  7  # Contents: 
  8  #   CompilationTest 
  9  #   CompiledResource 
 10  #   ExecutableTest 
 11  # 
 12  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 13  # 
 14  # For license terms see the file COPYING. 
 15  # 
 16  ######################################################################## 
 17   
 18  from compiler_test import CompilationStep, CompilerTest 
 19  from   qm.fields import * 
 20  from   qm.test.database import get_database 
 21  from   qm.test.result import * 
 22  from   qm.test.test import * 
 23  from   qm.test.resource import * 
 24  import qm.executable 
 25  from   qm.extension import parse_descriptor 
 26  from   qm.test.base import get_extension_class 
 27  from   compiler import Compiler 
 28  from   local_host import LocalHost 
 29   
 30   
31 -def _get_host(context, variable):
32 """Get a host instance according to a particular context variable. 33 Return a default 'LocalHost' host if the variable is undefined. 34 35 'context' -- The context to read the host descriptor from. 36 37 'variable' -- The name to which the host descriptor is bound. 38 39 returns -- A Host instance. 40 41 """ 42 43 target_desc = context.get(variable) 44 if target_desc is None: 45 target = LocalHost({}) 46 else: 47 f = lambda n: get_extension_class(n, "host", get_database()) 48 host_class, arguments = parse_descriptor(target_desc.strip(), f) 49 target = host_class(arguments) 50 return target
51 52 53 ######################################################################## 54 # Classes 55 ######################################################################## 56
57 -class CompilationTest(CompilerTest):
58 """A CompilationTest compiles and optionally runs an executable. 59 CompilationTest allows simple cross-testing. To run the executable on 60 anything other than localhost, specify a Host descriptor by means of the 61 context variable 'CompilationTest.target'.""" 62 63 options = SetField(TextField(description="""Test-specific options to pass to the compiler.""")) 64 ldflags = SetField(TextField(description="""Test-specific link flags to pass to the compiler.""")) 65 source_files = SetField(TextField(description="Source files to be compiled.")) 66 executable = TextField(description="The name of the executable to be compiled.") 67 execute = BooleanField(default_value = True, 68 description="Whether or not to run the compiled executable.") 69 70
71 - def Run(self, context, result):
77 78
79 - def _GetCompiler(self, context):
80 """The name of the compiler executable is taken from the context variable 81 'CompilationTest.compiler_path'.""" 82 83 name = context["CompilationTest.compiler_path"] 84 options = context.GetStringList("CompilationTest.compiler_options", []) 85 ldflags = context.GetStringList("CompilationTest.compiler_ldflags", []) 86 return Compiler(name, options, ldflags)
87 88
89 - def _GetCompilationSteps(self, context):
90 91 # Compile the executable in a single step so we can apply all 92 # options at once. 93 return [CompilationStep(self._GetCompiler(context), 94 Compiler.MODE_LINK, self.source_files, 95 self.options, self.ldflags, self.executable, [])]
96 97
98 - def _IsExecutionRequired(self):
99 100 return self.execute
101 102
103 - def _GetTarget(self, context):
104 105 return _get_host(context, "CompilationTest.target")
106 107
108 - def _CheckOutput(self, context, result, prefix, output, diagnostics):
109 110 if output: 111 result[prefix + "output"] = result.Quote(output) 112 113 return True
114 115
116 -class CompiledResource(Resource):
117 """A CompiledResource compiles an executable.""" 118 119 options = SetField(TextField(description="Resource-specific options to pass to the compiler.")) 120 source_files = SetField(TextField(description="Source files to be compiled.")) 121 executable = TextField(description="The name of the executable to be compiled.") 122 123
124 - def SetUp(self, context, result):
125 126 self._context = context 127 self._compiler = CompilationTest({'options':self.options, 128 'source_files':self.source_files, 129 'executable':self.executable, 130 'execute':False}, 131 qmtest_id = self.GetId(), 132 qmtest_database = self.GetDatabase()) 133 134 self._compiler.Run(context, result) 135 directory = self._compiler._GetDirectory(context) 136 self._executable = os.path.join(directory, self.executable) 137 context['CompiledResource.executable'] = self._executable
138 139
140 - def CleanUp(self, result):
141 142 self._compiler._RemoveDirectory(self._context, result)
143 144
145 -class ExecutableTest(Test):
146 """An ExecuableTest runs an executable from a CompiledResource. 147 ExecutableTest allows simple cross-testing. To run the executable on 148 anything other than localhost, specify a Host descriptor by means of the 149 context variable 'ExecutableTest.host'.""" 150 151 args = SetField(TextField(description="Arguments to pass to the executable.")) 152
153 - def Run(self, context, result):
154 155 executable = context['CompiledResource.executable'] 156 host = _get_host(context, 'ExecutableTest.host') 157 status, output = host.UploadAndRun(executable, self.args) 158 if not result.CheckExitStatus('ExecutableTest.', 'Program', status): 159 result.Fail('Unexpected exit_code')
160

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler_table-module.html0000664000076400007640000001170111122067145030153 0ustar stefanstefan qm.test.classes.compiler_table
Package qm :: Package test :: Package classes :: Module compiler_table
[hide private]
[frames] | no frames]

Module compiler_table

source code

Support for compiler test databases.

This module contains the 'CompilerTable' resource class which can be used by compiler test databases to determine which compiler to test based on context variables provided by the user.

Classes [hide private]
  CompilerTable
A map from programming languages to 'Compiler's.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.compilation_test_database-module.html0000664000076400007640000000244411122067144033161 0ustar stefanstefan compilation_test_database

Module compilation_test_database


Classes

CompilationTest
CompilationTestDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.compilation_test-module.html0000664000076400007640000000303711122067144031334 0ustar stefanstefan compilation_test

Module compilation_test


Classes

CompilationTest
CompiledResource
ExecutableTest

Functions


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist-module.html0000664000076400007640000001141611122067145023526 0ustar stefanstefan qm.dist
Package qm :: Package dist
[hide private]
[frames] | no frames]

Package dist

source code

Submodules [hide private]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web-pysrc.html0000664000076400007640000237444311122067153023230 0ustar stefanstefan qm.web
Package qm :: Module web
[hide private]
[frames] | no frames]

Source Code for Module qm.web

   1  ######################################################################## 
   2  # 
   3  # File:   web.py 
   4  # Author: Alex Samuel 
   5  # Date:   2001-02-08 
   6  # 
   7  # Contents: 
   8  #   Common code for implementing web user interfaces. 
   9  # 
  10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
  11  # 
  12  # For license terms see the file COPYING. 
  13  # 
  14  ######################################################################## 
  15   
  16  """Common code for implementing web user interfaces.""" 
  17   
  18  ######################################################################## 
  19  # imports 
  20  ######################################################################## 
  21   
  22  import BaseHTTPServer 
  23  import cgi 
  24  import diagnostic 
  25  import errno 
  26  import htmlentitydefs 
  27  import os 
  28  import os.path 
  29  import common 
  30  import qm.platform 
  31  import qm.user 
  32  import re 
  33  import SimpleHTTPServer 
  34  import SocketServer 
  35  import socket 
  36  import string 
  37  import structured_text 
  38  import sys 
  39  import temporary_directory 
  40  import time 
  41  import traceback 
  42  import types 
  43  import urllib 
  44  import user 
  45  import random 
  46   
  47  import qm.external.DocumentTemplate as DocumentTemplate 
  48  sys.path.insert(1, os.path.dirname(DocumentTemplate.__file__)) 
  49   
  50  ######################################################################## 
  51  # constants 
  52  ######################################################################## 
  53   
  54  session_id_field = "session" 
  55  """The name of the form field used to store the session ID.""" 
  56   
  57  ######################################################################## 
  58  # exception classes 
  59  ######################################################################## 
  60   
61 -class AddressInUseError(common.QMException):
62 pass
63 64 65
66 -class PrivilegedPortError(common.QMException):
67 pass
68 69 70
71 -class NoSessionError(common.QMException):
72 pass
73 74 75
76 -class InvalidSessionError(common.QMException):
77 pass
78 79 80 81 82 ######################################################################## 83 # classes 84 ######################################################################## 85
86 -class DtmlPage:
87 """Base class for classes to generate web pages from DTML. 88 89 The 'DtmlPage' object is used as the variable context when 90 generating HTML from DTML. Attributes and methods are available as 91 variables in DTML expressions. 92 93 This base class contains common variables and functions that are 94 available when generating all DTML files. 95 96 To generate HTML from a DTML template, instantiate a 'DtmlPage' 97 object, passing the name of the DTML template file to the 98 initializer function (or create a subclass which does this 99 automatically). Additional named attributes specified in the 100 initializer functions are set as attributes of the 'DtmlPage' 101 object, and thus available as variables in DTML Python expressions. 102 103 To generate HTML from the template, use the '__call__' method, 104 passing a 'WebRequest' object representing the request in response 105 to which the HTML page is being generated. The request set as the 106 'request' attribute of the 'DtmlPage' object. The 'WebRequest' 107 object may be omitted, if the generated HTML page is generic and 108 requires no information specific to the request or web session; in 109 this case, an empty request object is used. 110 111 This class also has an attribute, 'default_class', which is the 112 default 'DtmlPage' subclass to use when generating HTML. By 113 default, it is initialized to 'DtmlPage' itself, but applications 114 may derive a 'DtmlPage' subclass and point 'default_class' to it to 115 obtain customized versions of standard pages.""" 116 117 html_stylesheet = "/stylesheets/qm.css" 118 """The URL for the cascading stylesheet to use with generated pages.""" 119 120 common_javascript = "/common.js" 121 122 qm_bug_system_url = "mailto:qmtest@codesourcery.com" 123 """The public URL for the bug tracking system for the QM tools.""" 124 125
126 - def __init__(self, dtml_template, **attributes):
127 """Create a new page. 128 129 'dtml_template' -- The file name of the DTML template from which 130 the page is generated. The file is assumed to reside in the 131 'dtml' subdirectory of the configured share directory. 132 133 '**attributes' -- Additional attributes to include in the 134 variable context.""" 135 136 self.__dtml_template = dtml_template 137 for key, value in attributes.items(): 138 setattr(self, key, value)
139 140
141 - def __call__(self, request=None):
142 """Generate an HTML page from the DTML template. 143 144 'request' -- A 'WebRequest' object containing a page request in 145 response to which an HTML page is being generated. Session 146 information from the request may be used when generating the 147 page. The request may be 'None', if none is available. 148 149 returns -- The generated HTML text.""" 150 151 # Use an empty request if none was specified. 152 if request is None: 153 request = WebRequest("?") 154 self.request = request 155 # Construct the path to the template file. DTML templates are 156 # stored in the 'dtml' subdirectory of the share directory. 157 template_path = os.path.join(qm.get_share_directory(), "dtml", 158 self.__dtml_template) 159 # Generate HTML from the template. 160 html_file = DocumentTemplate.HTMLFile(template_path) 161 return html_file(self)
162 163
164 - def GetProgramName(self):
165 """Return the name of this application program.""" 166 167 return common.program_name
168 169
170 - def GetMainPageUrl(self):
171 """Return the URL for the main page.""" 172 173 return "/"
174 175
176 - def WebRequest(self, script_url, **fields):
177 """Convenience constructor for 'WebRequest' objects. 178 179 Constructs a 'WebRequest' using the specified 'script_url' and 180 'fields', using the request associated with this object as the 181 base request.""" 182 183 return apply(WebRequest, (script_url, self.request), fields)
184 185
186 - def GenerateXMLHeader(self):
187 """Return the XML header for the document.""" 188 189 return \ 190 '''<?xml version="1.0" encoding="iso-8859-1"?> 191 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 192 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 193 <html xmlns="http://www.w3.org/1999/xhtml">'''
194 195
196 - def GenerateHtmlHeader(self, description, headers=""):
197 """Return the header for an HTML document. 198 199 'description' -- A string describing this page. 200 201 'headers' -- Any additional HTML headers to place in the 202 '<head>' section of the HTML document.""" 203 204 return \ 205 '''<head> 206 <meta http-equiv="Content-Type" 207 content="text/html; charset=iso-8859-1"/> 208 %s 209 <meta http-equiv="Content-Style-Type" 210 content="text/css"/> 211 <link rel="stylesheet" 212 type="text/css" 213 href="%s"/> 214 <meta name="Generator" 215 content="%s"/> 216 <title>%s: %s</title> 217 </head> 218 ''' % (headers, self.html_stylesheet, self.GetProgramName(), 219 self.GetProgramName(), description)
220 221
222 - def GenerateStartBody(self, decorations=1):
223 """Return markup to start the body of the HTML document.""" 224 225 return "<body>"
226 227
228 - def GenerateEndBody(self, decorations=1):
229 """Return markup to end the body of the HTML document.""" 230 231 result = """ 232 <br /><br /> 233 """ 234 235 return result + self.GenerateStartScript(self.common_javascript) \ 236 + self.GenerateEndScript() + "</body>"
237 238
239 - def GenerateStartScript(self, uri=None):
240 """Return the HTML for beginning a script. 241 242 'uri' -- If not None, a string giving the URI of the script. 243 244 returns -- A string consisting of HTML for beginning an 245 embedded script. 246 247 'GenerateEndScript' must be called later to terminate the script.""" 248 249 # XHTML does not allow the "language" attribute but Netscape 4 250 # requires it. Also, in XHTML we should bracked the included 251 # script as CDATA, but that does not work with Netscape 4 252 # either. 253 result = '<script language="javascript" type="text/javascript"' 254 if uri is not None: 255 result = result + ' src="%s"' % uri 256 result = result + '>' 257 258 return result
259 260
261 - def GenerateEndScript(self):
262 """Return the HTML for ending an embedded script. 263 264 returns -- A string consisting of HTML for ending an 265 embedded script.""" 266 267 return '</script>'
268 269
270 - def MakeLoginForm(self, redirect_request=None, default_user_id=""):
271 if redirect_request is None: 272 # No redirection specified, so redirect back to this page. 273 redirect_request = self.request 274 request = redirect_request.copy("login") 275 request["_redirect_url"] = redirect_request.GetUrl() 276 # Use a POST method to submit the login form, so that passwords 277 # don't appear in web logs. 278 form = request.AsForm(method="post", name="login_form") 279 form = form + \ 280 ''' 281 <table cellpadding="0" cellspacing="0"> 282 <tr><td>User name:</td></tr> 283 <tr><td> 284 <input type="text" 285 size="16" 286 name="_login_user_name" 287 value="%s"/> 288 </td></tr> 289 <tr><td>Password:</td></tr> 290 <tr><td> 291 <input type="password" 292 size="16" 293 name="_login_password"/> 294 </td></tr> 295 <tr><td> 296 <input type="button" 297 value=" Log In " 298 onclick="document.login_form.submit();"/> 299 </td></tr> 300 </table> 301 </form> 302 ''' % default_user_id 303 return form
304 305
306 - def MakeButton(self, title, script_url, css_class=None, **fields):
307 """Generate HTML for a button to load a URL. 308 309 'title' -- The button title. 310 311 'script_url' -- The URL of the script. 312 313 'fields' -- Additional fields to add to the script request. 314 315 'css_class' -- The CSS class to use for the button, or 'None'. 316 317 The resulting HTML must be included in a form.""" 318 319 request = apply(WebRequest, [script_url, self.request], fields) 320 return make_button_for_request(title, request, css_class)
321 322
323 - def MakeImageUrl(self, image):
324 """Generate a URL for an image.""" 325 326 return "/images/%s" % image
327 328
329 - def MakeSpacer(self, width=1, height=1):
330 """Generate a spacer. 331 332 'width' -- The width of the spacer, in pixels. 333 334 'height' -- The height of the spacer, in pixels. 335 336 returns -- A transparent image of the requested size.""" 337 338 # 'clear.gif' is an image file containing a single transparent 339 # pixel, used for generating fixed spacers 340 return '<img border="0" width="%d" height="%d" src="%s"/>' \ 341 % (width, height, self.MakeImageUrl("clear.gif"))
342 343
344 - def MakeRule(self, color="black"):
345 """Generate a plain horizontal rule.""" 346 347 return ''' 348 <table border="0" cellpadding="0" cellspacing="0" width="100%%"> 349 <tr bgcolor="%s"><td>%s</td></tr> 350 </table> 351 ''' % (color, self.MakeSpacer())
352 353
354 - def UserIsInGroup(self, group_id):
355 """Return true if the user is a member of group 'group_id'. 356 357 Checks the group membership of the user associated with the 358 current session. 359 360 If there is no group named 'group_id' in the user database, 361 returns a false result.""" 362 363 user_id = self.request.GetSession().GetUserId() 364 try: 365 group = user.database.GetGroup(group_id) 366 except KeyError: 367 # No such group. 368 return 0 369 else: 370 return user_id in group
371 372 373 374 DtmlPage.default_class = DtmlPage 375 """Set the default DtmlPage implementation to the base class.""" 376 377 DtmlPage.web = sys.modules[DtmlPage.__module__] 378 """Make the functions in this module accessible.""" 379 380 381
382 -class HttpRedirect(Exception):
383 """Exception signalling an HTTP redirect response. 384 385 A script registered with a 'WebServer' instance can raise this 386 exception instead of returning HTML source text, to indicate that 387 the server should send an HTTP redirect (code 302) response to the 388 client instead of the usual code 202 response. 389 390 The exception argument is the URL of the redirect target. The 391 'request' attribute contains a 'WebRequest' for the redirect 392 target.""" 393
394 - def __init__(self, redirect_target_request):
395 """Construct a redirection exception. 396 397 'redirect_target_request' -- The 'WebRequest' to which to 398 redirect the client.""" 399 400 # Initialize the base class. 401 Exception.__init__(self, redirect_target_request.AsUrl()) 402 # Store the request itself. 403 self.request = redirect_target_request
404 405 406
407 -class WebRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
408 """Handler for HTTP requests. 409 410 This class groups callback functions that are invoked in response 411 to HTTP requests by 'WebServer'. 412 413 Don't define '__init__' or store any persistent information in 414 this class or subclasses; a new instance is created for each 415 request. Instead, store the information in the server instance, 416 available through the 'server' attribute.""" 417 418 # Update the extensions_map so that files are mapped to the correct 419 # content-types. 420 SimpleHTTPServer.SimpleHTTPRequestHandler.extensions_map.update( 421 { '.css' : 'text/css', 422 '.js' : 'text/javascript' } 423 ) 424
425 - def do_GET(self):
426 """Process HTTP GET requests.""" 427 428 # Parse the query string encoded in the URL, if any. 429 script_url, fields = parse_url_query(self.path) 430 # Build a request object and hand it off. 431 request = apply(WebRequest, (script_url, ), fields) 432 # Store the client's IP address with the request. 433 request.client_address = self.client_address[0] 434 435 self.__HandleRequest(request)
436
437 - def do_POST(self):
438 """Process HTTP POST requests.""" 439 440 # Determine the post's content type. 441 if self.headers.typeheader is None: 442 content_type_header = self.headers.type 443 else: 444 content_type_header = self.headers.typeheader 445 content_type, params = cgi.parse_header(content_type_header) 446 # We only know how to handle form-data submissions. 447 if content_type == "multipart/form-data": 448 # Parse the form data. 449 fields = cgi.parse_multipart(self.rfile, params) 450 # For each field, take the first value, discarding others. 451 # We don't support multi-valued fields. 452 for name, value in fields.items(): 453 if len(value) == 1: 454 fields[name] = value[0] 455 # There may be additional query arguments in the URL, so 456 # parse that too. 457 script_url, url_fields = parse_url_query(self.path) 458 # Merge query arguments from the form and from the URL. 459 fields.update(url_fields) 460 # Create and process a request. 461 request = apply(WebRequest, (script_url, ), fields) 462 # Store the client's IP address with the request. 463 request.client_address = self.client_address[0] 464 self.__HandleRequest(request) 465 else: 466 self.send_response(400, 467 "Unexpected request (POST of %s)." 468 % content_type)
469 470
471 - def __HandleScriptRequest(self, request):
472 try: 473 # Execute the script. The script returns the HTML 474 # text to return to the client. 475 try: 476 script_output = self.server.ProcessScript(request) 477 except NoSessionError, msg: 478 script_output = self.server.HandleNoSessionError(request, msg) 479 except InvalidSessionError, msg: 480 script_output = generate_login_form(request, msg) 481 except HttpRedirect, redirection: 482 # The script requested an HTTP redirect response to 483 # the client. 484 self.send_response(302) 485 self.send_header("Location", str(redirection)) 486 self.end_headers() 487 return 488 except SystemExit: 489 self.server.RequestShutdown() 490 script_output = ("<html><b>%s shutdown.</b></html>" 491 % qm.common.program_name) 492 except: 493 # Oops, the script raised an exception. Show 494 # information about the exception instead. 495 script_output = format_exception(sys.exc_info()) 496 # Send its output. 497 if isinstance(script_output, types.StringType): 498 # The return value from the script is a string. Assume it's 499 # HTML text, and send it appropriate.ly. 500 mime_type = "text/html" 501 data = script_output 502 elif isinstance(script_output, types.TupleType): 503 # The return value from the script is a tuple. Assume the 504 # first element is a MIME type and the second is result 505 # data. 506 mime_type, data = script_output 507 else: 508 raise ValueError 509 self.send_response(200) 510 self.send_header("Content-Type", mime_type) 511 self.send_header("Content-Length", len(data)) 512 # Since this is a dynamically-generated page, indicate that it 513 # should not be cached. The second header is necessary to support 514 # HTTP/1.0 clients. 515 self.send_header("Cache-Control", "no-cache") 516 self.send_header("Pragma", "no-cache") 517 self.end_headers() 518 try: 519 self.wfile.write(data) 520 except IOError: 521 # Couldn't write to the client. Oh well, it's probably a 522 # nework problem, or the user cancelled the operation, or 523 # the browser crashed... 524 pass
525 526
527 - def __HandleFileRequest(self, request, path):
528 # There should be no query arguments to a request for an 529 # ordinary file. 530 if len(request.keys()) > 0: 531 self.send_error(400, "Unexpected request.") 532 return 533 # Open the file. 534 try: 535 file = open(path, "rb") 536 except IOError: 537 # Send a generic 404 if there's a problem opening the file. 538 self.send_error(404, "File not found.") 539 return 540 # Send the file. 541 self.send_response(200) 542 self.send_header("Content-Type", self.guess_type(path)) 543 self.send_header("Cache-Control", "public") 544 self.end_headers() 545 self.copyfile(file, self.wfile)
546 547
548 - def __HandlePageCacheRequest(self, request):
549 """Process a retrieval request from the global page cache.""" 550 551 # Get the page from the cache. 552 page = self.server.GetCachedPage(request) 553 # Send it. 554 self.send_response(200) 555 self.send_header("Content-Type", "text/html") 556 self.send_header("Content-Length", str(len(page))) 557 self.send_header("Cache-Control", "public") 558 self.end_headers() 559 self.wfile.write(page)
560 561
562 - def __HandleSessionCacheRequest(self, request):
563 """Process a retrieval request from the session page cache.""" 564 565 # Extract the session ID. 566 session_id = request.GetSessionId() 567 if session_id is None: 568 # We should never get request for pages from the session 569 # cache without a session ID. 570 self.send_error(400, "Missing session ID.") 571 return 572 # Get the page from the cache. 573 page = self.server.GetCachedPage(request, session_id) 574 # Send it. 575 self.send_response(200) 576 self.send_header("Content-Type", "text/html") 577 self.send_header("Content-Length", str(len(page))) 578 self.send_header("Cache-Control", "private") 579 self.end_headers() 580 self.wfile.write(page)
581 582
583 - def __HandleRequest(self, request):
584 """Process a request from a GET or POST operation. 585 586 'request' -- A 'WebRequest' object.""" 587 588 if request.GetScriptName() == _page_cache_name: 589 # It's a request from the global page cache. 590 self.__HandlePageCacheRequest(request) 591 elif request.GetScriptName() == _session_cache_name: 592 # It's a request from the session page cache. 593 self.__HandleSessionCacheRequest(request) 594 # Check if this request corresponds to a script. 595 elif self.server.IsScript(request): 596 # It is, so run it. 597 self.__HandleScriptRequest(request) 598 else: 599 # Now check if it maps onto a file. Translate the script URL 600 # into a file system path. 601 path = self.server.TranslateRequest(request) 602 # Is it a file? 603 if path is not None and os.path.isfile(path): 604 self.__HandleFileRequest(request, path) 605 606 else: 607 # The server doesn't know about this URL. 608 self.send_error(404, "File not found.")
609 610
611 - def log_message(self, format, *args):
612 """Log a message; overrides 'BaseHTTPRequestHandler.log_message'.""" 613 614 # Write an Apache-style log entry via the server instance. 615 message = "%s - - [%s] %s\n" \ 616 % (self.address_string(), 617 self.log_date_time_string(), 618 format%args) 619 self.server.LogMessage(message)
620 621 622
623 -class HTTPServer(BaseHTTPServer.HTTPServer):
624 """Workaround for problems in 'BaseHTTPServer.HTTPServer'. 625 626 The Python 1.5.2 library's implementation of 627 'BaseHTTPServer.HTTPServer.server_bind' seems to have difficulties 628 when the local host address cannot be resolved by 'gethostbyaddr'. 629 This may happen for a variety of reasons, such as reverse DNS 630 misconfiguration. This subclass fixes that problem.""" 631
632 - def server_bind(self):
633 """Override 'server_bind' to store the server name.""" 634 635 # The problem occurs when an empty host name is specified as the 636 # local address to which the socket binds. Specifying an empty 637 # host name causes the socket to bind to 'INADDR_ANY', which 638 # indicates that the socket should be bound to all interfaces. 639 # 640 # If the socket is bound to 'INADDR_ANY', 'gethostname' returns 641 # '0.0.0.0'. In this case, 'BaseHTTPServer' tries unhelpfully 642 # to obtain a host name to associate with the socket by calling 643 # 'gethostname' and then 'gethostbyaddr' on the result. This 644 # will raise a socket error if reverse lookup on the (primary) 645 # host address fails. So, we use our own method to retrieve the 646 # local host name, which fails more gracefully under this 647 # circumstance. 648 649 SocketServer.TCPServer.server_bind(self) 650 host, port = self.socket.getsockname() 651 652 # Use the primary host name if we're bound to all interfaces. 653 # This is a bit misleading, because the primary host name may 654 # not be bound to all interfaces. 655 if not host or host == '0.0.0.0': 656 host = socket.gethostname() 657 658 # Try the broken 'BaseHTTPServer' implementation. 659 try: 660 hostname, hostnames, hostaddrs = socket.gethostbyaddr(host) 661 if '.' not in hostname: 662 for host in hostnames: 663 if '.' in host: 664 hostname = host 665 break 666 except socket.error: 667 # If it bombs, use our more lenient method. 668 hostname = qm.platform.get_host_name() 669 670 self.server_name = hostname 671 self.server_port = port
672 673 674
675 -class WebServer(HTTPServer):
676 """A web server that serves ordinary files and dynamic content. 677 678 To configure the server to serve ordinary files, register the 679 directories containing those files with 680 'RegisterPathTranslations'. An arbitrary number of directories 681 may be specified, and all files in each directory and under it 682 are made available. 683 684 To congifure the server to serve dynamic content, register dynamic 685 URLs with 'RegisterScript'. A request matching the URL exactly 686 will cause the server to invoke the provided function. 687 688 The web server resolves request URLs in a two-step process. 689 690 1. The server checks if the URL matches exactly a script URL. If 691 a match is found, the corresponding function is invoked, and 692 its return value is sent to the client. 693 694 2. The server checks whether any registered path translation is a 695 prefix of the reqest URL. If it is, the path is translated 696 into a file system path, and the corresponding file is 697 returned. 698 699 The server also provides a rudimentary manual caching mechanism for 700 generated pages. The application may insert a generated page into 701 the page cache, if it is expected not to change. The application 702 can use this mechanism: 703 704 - to supress duplicate generation of the same page, 705 706 - or to pre-generate a page that may be requested later. This is 707 particularly handy if generating the page requires state 708 information that would be difficult to reconstruct later. 709 710 Pages may be shared across sessions, or may be specific to a 711 particular session.""" 712 713
714 - def __init__(self, 715 port, 716 address="", 717 log_file=sys.stderr):
718 """Create a new web server. 719 720 'port' -- The port on which to accept connections. If 'port' 721 is '0', then any port will do. 722 723 'address' -- The local address to which to bind. An empty 724 string means bind to all local addresses. 725 726 'log_file' -- A file object to which to write log messages. 727 If it's 'None', no logging. 728 729 The server is not started until the 'Bind' and 'Run' methods are 730 invoked.""" 731 732 self.__port = port 733 self.__address = address 734 self.__log_file = log_file 735 self.__scripts = {} 736 self.__translations = {} 737 self.__shutdown_requested = 0 738 739 self.RegisterScript("/problems.html", self._HandleProblems) 740 self.RegisterScript("/", self._HandleRoot) 741 742 # Register the common JavaScript. 743 self.RegisterPathTranslation( 744 "/common.js", qm.get_share_directory("web", "common.js")) 745 746 self.__cache_dir = temporary_directory.TemporaryDirectory() 747 self.__cache_path = self.__cache_dir.GetPath() 748 os.mkdir(os.path.join(self.__cache_path, "sessions"), 0700) 749 750 # Create a temporary attachment store to process attachment data 751 # uploads. 752 self.__temporary_store = qm.attachment.TemporaryAttachmentStore() 753 self.RegisterScript(qm.fields.AttachmentField.upload_url, 754 self.__temporary_store.HandleUploadRequest)
755 756 # Don't call the base class __init__ here, since we don't want 757 # to create the web server just yet. Instead, we'll call it 758 # when it's time to run the server. 759 760
761 - def RegisterScript(self, script_path, script):
762 """Register a dynamic URL. 763 764 'script_path' -- The URL for this script. A request must 765 match this path exactly. 766 767 'script' -- A callable to invoke to generate the page 768 content. 769 770 If you register 771 772 web_server.RegisterScript('/cgi-bin/myscript', make_page) 773 774 then the URL 'http://my.server.com/cgi-bin/myscript' will 775 respond with the output of calling 'make_page'. 776 777 The script is passed a single argument, a 'WebRequest' 778 instance. It returns the HTML source, as a string, of the 779 page it generates. If it returns a tuple instead, the first 780 element is taken to be a MIME type and the second is the data. 781 782 The script may instead raise an 'HttpRedirect' instance, 783 indicating an HTTP redirect response should be sent to the 784 client.""" 785 786 self.__scripts[script_path] = script
787 788
789 - def RegisterPathTranslation(self, url_path, file_path):
790 """Register a path translation. 791 792 'url_path' -- The path in URL-space to map from. URLs of 793 which 'url_path' is a prefix can be translated. 794 795 'file_path' -- The file system path corresponding to 796 'url_path'. 797 798 For example, if you register 799 800 web_server.RegisterPathTranslation('/images', '/path/to/pictures') 801 802 the URL 'http://my.server.com/images/big/tree.gif' will be 803 mapped to the file path '/path/to/pictures/big/tree.gif'.""" 804 805 self.__translations[url_path] = file_path
806 807
808 - def IsScript(self, request):
809 """Return a true value if 'request' corresponds to a script.""" 810 811 return self.__scripts.has_key(request.GetUrl())
812 813
814 - def ProcessScript(self, request):
815 """Process 'request' as a script. 816 817 'request' -- A 'WebRequest' object. 818 819 returns -- The output of the script.""" 820 821 return self.__scripts[request.GetUrl()](request)
822 823
824 - def TranslateRequest(self, request):
825 """Translate the URL in 'request' to a file system path. 826 827 'request' -- A 'WebRequest' object. 828 829 returns -- A path to the corresponding file, or 'None' if the 830 request URL didn't match any translations.""" 831 832 path = request.GetUrl() 833 # Loop over translations. 834 for url_path, file_path in self.__translations.items(): 835 # Is this translation a prefix of the URL? 836 if path[:len(url_path)] == url_path: 837 # Yes. First cut off the prefix that matched. 838 sub_path = path[len(url_path):] 839 # Make sure what's left doesn't look like an absolute path. 840 if os.path.isabs(sub_path): 841 sub_path = sub_path[1:] 842 # Construct the file system path. 843 if sub_path: 844 file_path = os.path.join(file_path, sub_path) 845 return file_path 846 # No match was found. 847 return None
848 849
850 - def Bind(self):
851 """Bind the server to the specified address and port. 852 853 Does not start serving.""" 854 855 # Initialize the base class here. This binds the server 856 # socket. 857 try: 858 # Base class initialization. Unfortunately, the base 859 # class's initializer function (actually, its own base 860 # class's initializer function, 'TCPServer.__init__') 861 # doesn't provide a way to set options on the server socket 862 # after it's created but before it's bound. 863 # 864 # If the SO_REUSEADDR option is not set before the socket is 865 # bound, the bind operation will fail if there is alreay a 866 # socket on the same port in the TIME_WAIT state. This 867 # happens most frequently if a server is terminated and then 868 # promptly restarted on the same port. Eventually, the 869 # socket is cleaned up and the port number is available 870 # again, but it's a big nuisance. The SO_REUSEADDR option 871 # allows the new socket to be bound to the same port 872 # immediately. 873 # 874 # So that we can insert the call to 'setsockopt' between the 875 # socket creation and bind, we duplicate the body of 876 # 'TCPServer.__init__' here and add the call. 877 self.RequestHandlerClass = WebRequestHandler 878 self.socket = socket.socket(self.address_family, 879 self.socket_type) 880 self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 881 self.server_address = (self.__address, self.__port) 882 self.server_bind() 883 self.server_activate() 884 except socket.error, error: 885 error_number, message = error 886 if error_number == errno.EADDRINUSE: 887 # The specified address/port is already in use. 888 if self.__address == "": 889 address = "port %d" % self.__port 890 else: 891 address = "%s:%d" % (self.__address, self.__port) 892 raise AddressInUseError, address 893 elif error_number == errno.EACCES: 894 # Permission denied. 895 raise PrivilegedPortError, "port %d" % self.__port 896 else: 897 # Propagate other exceptions. 898 raise
899 900
901 - def Run(self):
902 """Start the web server. 903 904 preconditions -- The server must be bound.""" 905 906 while not self.__shutdown_requested: 907 self.handle_request()
908 909
910 - def RequestShutdown(self):
911 """Shut the server down after processing the current request.""" 912 913 self.__shutdown_requested = 1
914 915
916 - def LogMessage(self, message):
917 """Log a message.""" 918 919 if self.__log_file is not None: 920 self.__log_file.write(message) 921 self.__log_file.flush()
922 923
924 - def GetServerAddress(self):
925 """Return the host address on which this server is running. 926 927 returns -- A pair '(hostname, port)'.""" 928 929 return (self.server_name, self.server_port)
930 931
933 """Return the 'AttachmentStore' used for new 'Attachment's. 934 935 returns -- The 'AttachmentStore' used for new 'Attachment's.""" 936 937 return self.__temporary_store
938 939
940 - def MakeButtonForCachedPopup(self, 941 label, 942 html_text, 943 request=None, 944 window_width=480, 945 window_height=240):
946 """Construct a button for displaying a cached popup page. 947 948 'label' -- The button label. 949 950 'html_text' -- The HTML source for the popup page. 951 952 'window_width' -- The width, in pixels, of the popup window. 953 954 'window_height' -- The height, in pixels, of the popup window. 955 956 returns -- HTML source for the button. The button must be placed 957 within a form element.""" 958 959 # Place the page in the page cache. 960 if request is None: 961 session_id = None 962 else: 963 session_id = request.GetSessionId() 964 page_url = self.CachePage(html_text, session_id).AsUrl() 965 966 return make_button_for_popup(label, page_url, window_width, 967 window_height)
968 969
970 - def MakeConfirmationDialog(self, message, url):
971 """Generate JavaScript for a confirmation dialog box. 972 973 'url' -- The location in the main browser window is set to the URL 974 if the user confirms the action. 975 976 See 'make_popup_dialog_script' for a description of 'function_name' 977 and 'message' and information on how to use the return value.""" 978 979 # If the user clicks the "Yes" button, advance the main browser 980 # page. 981 open_script = "window.opener.document.location = %s;" \ 982 % make_javascript_string(url) 983 # Two buttons: "Yes" and "No". "No" doesn't do anything. 984 buttons = [ 985 ( "Yes", open_script ), 986 ( "No", None ), 987 ] 988 return self.MakePopupDialog(message, buttons, title="Confirm")
989 990
991 - def MakePopupDialog(self, message, buttons, title=""):
992 """Generate JavaScript to show a popup dialog box. 993 994 The popup dialog box displays a message and one or more buttons. 995 Each button can have a JavaScript statement (or statements) 996 associated with it; if the button is clicked, the statement is 997 invoked. After any button is clicked, the popup window is closed as 998 well. 999 1000 'message' -- HTML source of the message to display in the popup 1001 window. 1002 1003 'buttons' -- A sequence of button specifications. Each is a pair 1004 '(caption, script)'. 'caption' is the button caption. 'script' is 1005 the JavaScript statement to invoke when the button is clicked, or 1006 'None'. 1007 1008 'title' -- The popup window title. 1009 1010 returns -- JavaScript statements to show the dialog box, suiteable 1011 for use as an event handler.""" 1012 1013 # Construct the popup page. 1014 page = make_popup_page(message, buttons, title) 1015 page_url = self.CachePage(page).AsUrl() 1016 # Construct the JavaScript variable and function. 1017 return "window.open('%s', 'popup', 'width=480,height=200,resizable')" \ 1018 % page_url
1019 1020
1021 - def CachePage(self, page_text, session_id=None):
1022 """Cache an HTML page. 1023 1024 'page_text' -- The text of the page. 1025 1026 'session_id' -- The session ID for this page, or 'None'. 1027 1028 returns -- A 'WebRequest' object with which the cached page can be 1029 retrieved later. 1030 1031 If 'session_id' is 'None', the page is placed in the global page 1032 cache. Otherwise, it is placed in the session page cache for that 1033 session.""" 1034 1035 if session_id is None: 1036 # No path was specified. Place the file in the top directory. 1037 dir_path = self.__cache_path 1038 script_name = _page_cache_name 1039 else: 1040 # A session was specified. Put the file in a subdirectory named 1041 # after the session. 1042 dir_path = os.path.join(self.__cache_path, "sessions", session_id) 1043 script_name = _session_cache_name 1044 # Create that directory if it doesn't exist. 1045 if not os.path.isdir(dir_path): 1046 os.mkdir(dir_path, 0700) 1047 1048 # Generate a name for the page. 1049 global _counter 1050 page_name = str(_counter) 1051 _counter = _counter + 1 1052 # Write it. 1053 page_file_name = os.path.join(dir_path, page_name) 1054 page_file = open(page_file_name, "w", 0600) 1055 page_file.write(page_text) 1056 page_file.close() 1057 1058 # Return a request for this page. 1059 request = WebRequest(script_name, page=page_name) 1060 if session_id is not None: 1061 request.SetSessionId(session_id) 1062 return request
1063 1064
1065 - def GetCachedPage(self, request, session_id=None):
1066 """Retrieve a page from the page cache. 1067 1068 'request' -- The URL requesting the page from the cache. 1069 1070 'session_id' -- The session ID for the request, or 'None'. 1071 1072 returns -- The cached page, or a placeholder page if the page was 1073 not found in the cache. 1074 1075 If 'session_id' is 'None', the page is retrieved from the global 1076 page cache. Otherwise, it is retrieved from the session page cache 1077 for that session.""" 1078 1079 page_file_name = self.__GetPathForCachedPage(request, session_id) 1080 if os.path.isfile(page_file_name): 1081 # Return the page. 1082 return open(page_file_name, "r").read() 1083 else: 1084 # Oops, no such page. Generate a placeholder. 1085 return """ 1086 <html> 1087 <body> 1088 <h3>Cache Error</h3> 1089 <p>You have requested a page that no longer is in the server's 1090 cache. The server may have been restarted, or the page may 1091 have expired. Please start over.</p> 1092 <!-- %s --> 1093 </body> 1094 </html> 1095 """ % url
1096 1097
1098 - def __GetPathForCachedPage(self, request, session_id):
1099 """Return the path for a cached page. 1100 1101 'request' -- The URL requesting the page from the cache. 1102 1103 'session_id' -- The session ID for the request, or 'None'.""" 1104 1105 if session_id is None: 1106 dir_path = self.__cache_path 1107 else: 1108 # Construct the path to the directory containing pages in the 1109 # cache for 'session_id'. 1110 dir_path = os.path.join(self.__cache_path, "sessions", session_id) 1111 # Construct the path to the file containing the page. 1112 page_name = request["page"] 1113 return os.path.join(dir_path, page_name)
1114 1115
1116 - def HandleNoSessionError(self, request, message):
1117 """Handler when session is absent.""" 1118 1119 # There's no session specified in this request. Try to 1120 # create a session for the default user. 1121 try: 1122 user_id = user.authenticator.AuthenticateDefaultUser() 1123 except user.AuthenticationError: 1124 # Couldn't get a default user session, so bail. 1125 return generate_login_form(request, message) 1126 # Authenticating the default user succeeded. Create an implicit 1127 # session with the default user ID. 1128 session = Session(request, user_id) 1129 # Redirect to the same page but using the new session ID. 1130 request.SetSessionId(session.GetId()) 1131 raise HttpRedirect(request)
1132 1133
1134 - def _HandleProblems(self, request):
1135 """Handle internal errors.""" 1136 1137 return DtmlPage.default_class("problems.dtml")(request)
1138 1139
1140 - def _HandleRoot(self, request):
1141 """Handle the '/' URL.""" 1142 1143 raise HttpRedirect, WebRequest("/static/index.html")
1144 1145
1146 - def handle_error(self, request, client_address):
1147 """Handle an error gracefully.""" 1148 1149 # The usual cause of an error is a broken pipe; the user 1150 # may have clicked on something else in the browser before 1151 # we have time to finish writing the response to the browser. 1152 # In that case, we will get EPIPE when trying to write to the 1153 # pipe. 1154 # 1155 # The default behavior (inherited from BaseHTTPServer) 1156 # is to print the traceback to the standard error, which is 1157 # definitely not the right behavior for QMTest. If there 1158 # are any errors for which we must take explicit action, 1159 # we will have to add logic to handle them here. 1160 return
1161 1162 1163
1164 -class WebRequest:
1165 """An object representing a request from the web server. 1166 1167 A 'WebRequest' object behaves as a dictionary of key, value pairs 1168 representing query arguments, for instance query fields in a POST, 1169 or arguments encoded in a URL query string. It has some other 1170 methods as well.""" 1171
1172 - def __init__(self, script_url, base=None, keep_fields=False, **fields):
1173 """Create a new request object. 1174 1175 'script_url' -- The URL of the script that processes this 1176 query. 1177 1178 'base' -- A request object from which the session ID will be 1179 duplicated, or 'None'. 1180 1181 'fields' -- The query arguments.""" 1182 1183 self.__url = script_url 1184 self.__fields = {} 1185 if base and keep_fields: 1186 self.__fields.update(base.__fields) 1187 self.__fields.update(fields) 1188 # Copy the session ID from the base. 1189 if base is not None: 1190 session = base.GetSessionId() 1191 if session is not None: 1192 self.SetSessionId(session) 1193 self.client_address = base.client_address
1194 1195
1196 - def __str__(self):
1197 str = "WebRequest for %s\n" % self.__url 1198 for name, value in self.__fields.items(): 1199 str = str + "%s=%s\n" % (name, repr(value)) 1200 return str
1201 1202
1203 - def GetUrl(self):
1204 """Return the URL of the script that processes this request.""" 1205 1206 return self.__url
1207 1208
1209 - def GetScriptName(self):
1210 """Return the name of the script that processes this request. 1211 1212 The script name is the final element of the full URL path.""" 1213 1214 return string.split(self.__url, "/")[-1]
1215 1216
1217 - def SetSessionId(self, session_id):
1218 """Set the session ID for this request to 'session_id'.""" 1219 1220 self[session_id_field] = session_id
1221 1222
1223 - def GetSessionId(self):
1224 """Return the session ID for this request. 1225 1226 returns -- A session ID, or 'None'.""" 1227 1228 return self.get(session_id_field, None)
1229 1230
1231 - def GetSession(self):
1232 """Return the session for this request. 1233 1234 raises -- 'NoSessionError' if no session ID is specified in the 1235 request. 1236 1237 raises -- 'InvalidSessionError' if the session ID specified in 1238 the request is invalid.""" 1239 1240 session_id = self.GetSessionId() 1241 if session_id is None: 1242 raise NoSessionError, qm.error("session required") 1243 else: 1244 return get_session(self, session_id)
1245 1246
1247 - def AsUrl(self, last_argument=None):
1248 """Return the URL representation of this request. 1249 1250 'fields_at_end' -- If not 'None', the name of the URL query 1251 arguments that should be placed last in the list of arugmnets 1252 (other than this, the order of query arguments is not 1253 defined).""" 1254 1255 if len(self.keys()) == 0: 1256 # No query arguments; just use the script URL. 1257 return self.GetUrl() 1258 else: 1259 # Encode query arguments into the URL. 1260 return "%s?%s" % (self.GetUrl(), urllib.urlencode(self))
1261 1262
1263 - def AsForm(self, method="get", name=None):
1264 """Return an opening form tag for this request. 1265 1266 'method' -- The HTML method to use for the form, either "get" or 1267 "post". 1268 1269 'name' -- A name for the form, or 'None'. 1270 1271 returns -- An opening form tag for the request, plus hidden 1272 input elements for arguments to the request. 1273 1274 The caller must add additional inputs, the submit input, and 1275 close the form tag.""" 1276 1277 if name is not None: 1278 name_attribute = 'name="%s"' % name 1279 else: 1280 name_attribute = '' 1281 # Generate the form tag. 1282 if method == "get": 1283 result = '<form method="get" action="%s" %s>\n' \ 1284 % (self.GetUrl(), name_attribute) 1285 elif method == "post": 1286 result = '''<form %s 1287 method="post" 1288 enctype="multipart/form-data" 1289 action="%s">\n''' \ 1290 % (name_attribute, self.GetUrl()) 1291 else: 1292 raise ValueError, "unknown method %s" % method 1293 # Add hidden inputs for the request arguments. 1294 for name, value in self.items(): 1295 result = result \ 1296 + '<input type="hidden" name="%s" value="%s">\n' \ 1297 % (name, value) 1298 1299 return result
1300 1301 1302 # Methods to emulate a mapping. 1303
1304 - def __getitem__(self, key):
1305 return self.__fields[key]
1306 1307
1308 - def __setitem__(self, key, value):
1309 self.__fields[key] = value
1310 1311
1312 - def __delitem__(self, key):
1313 del self.__fields[key]
1314 1315
1316 - def get(self, key, default=None):
1317 return self.__fields.get(key, default)
1318 1319
1320 - def keys(self):
1321 return self.__fields.keys()
1322 1323
1324 - def has_key(self, key):
1325 return self.__fields.has_key(key)
1326 1327
1328 - def items(self):
1329 return self.__fields.items()
1330 1331
1332 - def copy(self, url=None, **fields):
1333 """Return a duplicate of this request. 1334 1335 'url' -- The URL for the request copy. If 'None', use the 1336 URL of the source. 1337 1338 '**fields' -- Additional fields to set in the copy.""" 1339 1340 # Copy the URL unless another was specified. 1341 if url is None: 1342 url = self.__url 1343 # Copy fields, and update with any that were specified 1344 # additionally. 1345 new_fields = self.__fields.copy() 1346 new_fields.update(fields) 1347 # Make the request. 1348 new_request = apply(WebRequest, (url, ), new_fields) 1349 # Copy the client address, if present. 1350 if hasattr(self, "client_address"): 1351 new_request.client_address = self.client_address 1352 1353 return new_request
1354 1355 1356
1357 -class CGIWebRequest:
1358 """A 'WebRequest' object initialized from the CGI environment.""" 1359
1360 - def __init__(self):
1361 """Create a new request from the current CGI environment. 1362 1363 preconditions -- The CGI environment (environment variables 1364 etc.) must be in place.""" 1365 1366 assert os.environ.has_key("GATEWAY_INTERFACE") 1367 assert os.environ["GATEWAY_INTERFACE"][:3] == "CGI" 1368 1369 self.__fields = cgi.FieldStorage()
1370 1371
1372 - def GetUrl(self):
1373 return os.environ["SCRIPT_NAME"]
1374 1375
1376 - def __getitem__(self, key):
1377 return self.__fields[key].value
1378 1379
1380 - def keys(self):
1381 return self.__fields.keys()
1382 1383
1384 - def has_key(self, key):
1385 return self.__fields.has_key(key)
1386 1387
1388 - def copy(self):
1389 """Return a copy of the request. 1390 1391 The copy isn't tied to the CGI environment, so it can be 1392 modified safely.""" 1393 1394 fields = {} 1395 for key in self.keys(): 1396 fields[key] = self[key] 1397 return apply(WebRequest, (self.GetUrl(), ), fields)
1398 1399
1400 -def _create_session_id():
1401 1402 # Seed the random number generator with the system time. 1403 random.seed() 1404 try: # hashlib is available since Python 2.5 1405 import hashlib 1406 md5 = hashlib.md5() 1407 md5.update("%f" % random.random()) 1408 digest = md5.digest() 1409 except: # fall back to md5 on older Python versions 1410 import md5 1411 # FIXME: Security: Is this OK? 1412 digest = md5.new("%f" % random.random()).digest() 1413 1414 # Convert the digest, which is a 16-character string, 1415 # to a sequence hexadecimal bytes. 1416 digest = [hex(ord(c))[2:] for c in digest] 1417 # Convert it to a 32-character string. 1418 return ''.join(digest)
1419 1420
1421 -class Session:
1422 """A persistent user session. 1423 1424 A 'Session' object represents an ongoing user interaction with the 1425 web server.""" 1426
1427 - def __init__(self, request, user_id, expiration_timeout=21600):
1428 """Create a new session. 1429 1430 'request' -- A 'WebRequest' object in response to which this 1431 session is created. 1432 1433 'user_id' -- The ID of the user owning the session. 1434 1435 'expiration_timeout -- The expiration time, in seconds. If a 1436 session is not accessed for this duration, it is expired and no 1437 longer usable.""" 1438 1439 self.__user_id = user_id 1440 self.__expiration_timeout = expiration_timeout 1441 # Extract the client's IP address from the request. 1442 self.__client_address = request.client_address 1443 1444 self.__id = _create_session_id() 1445 1446 self.Touch() 1447 1448 # Record ourselves in the sessions map. 1449 sessions[self.__id] = self
1450 1451
1452 - def Touch(self):
1453 """Update the last access time on the session to now.""" 1454 1455 self.__last_access_time = time.time()
1456 1457
1458 - def GetId(self):
1459 """Return the session ID.""" 1460 1461 return self.__id
1462 1463
1464 - def GetUserId(self):
1465 """Return the ID of the user who owns this session.""" 1466 1467 return self.__user_id
1468 1469
1470 - def GetUser(self):
1471 """Return the user record for the owning user. 1472 1473 returns -- A 'qm.user.User' object.""" 1474 1475 return user.database[self.__user_id]
1476 1477
1478 - def IsDefaultUser(self):
1479 """Return true if the owning user is the default user.""" 1480 1481 return self.GetUserId() == user.database.GetDefaultUserId()
1482 1483
1484 - def IsExpired(self):
1485 """Return true if this session has expired.""" 1486 1487 age = time.time() - self.__last_access_time 1488 return age > self.__expiration_timeout
1489 1490
1491 - def Validate(self, request):
1492 """Make sure the session is OK for a request. 1493 1494 'request' -- A 'WebRequest' object. 1495 1496 raises -- 'InvalidSessionError' if the session is invalid for 1497 the request.""" 1498 1499 # Make sure the client IP address in the request matches that 1500 # for this session. 1501 if self.__client_address != request.client_address: 1502 raise InvalidSessionError, qm.error("session wrong IP") 1503 # Make sure the session hasn't expired. 1504 if self.IsExpired(): 1505 raise InvalidSessionError, qm.error("session expired")
1506 1507 1508 1509 ######################################################################## 1510 # functions 1511 ######################################################################## 1512
1513 -def parse_url_query(url):
1514 """Parse a URL-encoded query. 1515 1516 This function parses query strings encoded in URLs, such as 1517 '/script.cgi?key1=val1&key2=val2'. For this example, it would 1518 return '("/script.cgi", {"key1" : "val1", "key2" : "val2"})' 1519 1520 'url' -- The URL to parse. 1521 1522 returns -- A pair containing the the base script path and a 1523 mapping of query field names to values.""" 1524 1525 # Check if the script path is a URL-encoded query. 1526 if "?" in url: 1527 # Yes. Everything up to the question mark is the script 1528 # path; stuff after that is the query string. 1529 script_url, query_string = string.split(url, "?", 1) 1530 # Parse the query string. 1531 fields = cgi.parse_qs(query_string) 1532 # We only handle one instance of each key in the query. 1533 # 'parse_qs' produces a list of values for each key; check 1534 # that each list contains only one item, and replace the 1535 # list with that item. 1536 for key, value_list in fields.items(): 1537 if len(value_list) != 1: 1538 # Tell the client that we don't like this query. 1539 print "WARNING: Multiple values in query." 1540 fields[key] = value_list[0] 1541 else: 1542 # No, it's just an ordinary URL. 1543 script_url = url 1544 fields = {} 1545 1546 script_url = urllib.unquote(script_url) 1547 return (script_url, fields)
1548 1549
1550 -def http_return_html(html_text, stream=sys.stdout):
1551 """Generate an HTTP response consisting of HTML text. 1552 1553 'html_text' -- The HTML souce text to return. 1554 1555 'stream' -- The stream to write the response, by default 1556 'sys.stdout.'.""" 1557 1558 stream.write("Content-type: text/html\n\n") 1559 stream.write(html_text)
1560 1561
1562 -def http_return_exception(exc_info=None, stream=sys.stdout):
1563 """Generate an HTTP response for an exception. 1564 1565 'exc_info' -- A three-element tuple containing exception info, of 1566 the form '(type, value, traceback)'. If 'None', use the exception 1567 currently being handled. 1568 1569 'stream' -- The stream to write the response, by default 1570 'sys.stdout.'.""" 1571 1572 if exc_info == None: 1573 exc_info = sys.exc_info() 1574 1575 stream.write("Content-type: text/html\n\n"); 1576 stream.write(format_exception(exc_info))
1577 1578
1579 -def format_exception(exc_info):
1580 """Format an exception as HTML. 1581 1582 'exc_info' -- A three-element tuple containing exception info, of 1583 the form '(type, value, traceback)'. 1584 1585 returns -- A string containing a complete HTML file displaying the 1586 exception.""" 1587 1588 # Break up the exection info tuple. 1589 type, value, trace = exc_info 1590 # Format the traceback, with a newline separating elements. 1591 traceback_listing = string.join(traceback.format_tb(trace), "\n") 1592 # Construct a page info object to generate an exception page. 1593 page = DtmlPage.default_class( 1594 "exception.dtml", 1595 exception_type=type, 1596 exception_value=value, 1597 traceback_listing=traceback_listing) 1598 # Generate the page. 1599 return page()
1600 1601 1602
1603 -def escape(text):
1604 """Escape special characters in 'text' for formatting as HTML.""" 1605 1606 return structured_text.escape_html_entities(text)
1607 1608 1609 # A regular expression that matches anything that looks like an entity. 1610 __entity_regex = re.compile("&(\w+);") 1611 1612 1613 # A function that returns the replacement for an entity matched by the 1614 # above expression.
1615 -def __replacement_for_entity(match):
1616 entity = match.group(1) 1617 try: 1618 return htmlentitydefs.entitydefs[entity] 1619 except KeyError: 1620 return "&%s;" % entity
1621 1622
1623 -def unescape(text):
1624 """Undo 'escape' by replacing entities with ordinary characters.""" 1625 1626 return __entity_regex.sub(__replacement_for_entity, text)
1627 1628
1629 -def format_structured_text(text):
1630 """Render 'text' as HTML.""" 1631 1632 if text == "": 1633 # In case the text is the only contents of a table cell -- in 1634 # which case an empty string will produce undesirable visual 1635 # effects -- return a single space anyway. 1636 return "&nbsp;" 1637 else: 1638 return structured_text.to_html(text)
1639 1640
1641 -def make_url(script_name, base_request=None, **fields):
1642 """Create a request and return a URL for it. 1643 1644 'script_name' -- The script name for the request. 1645 1646 'base_request' -- If not 'None', the base request for the generated 1647 request. 1648 1649 'fields' -- Additional fields to include in the request.""" 1650 1651 request = apply(WebRequest, (script_name, base_request), fields) 1652 return request.AsUrl()
1653 1654
1655 -def make_button_for_request(title, request, css_class=None):
1656 """Generate HTML for a button. 1657 1658 Note that the caller is responsible for making sure the resulting 1659 button is placed within a form element. 1660 1661 'title' -- The button label. 1662 1663 'request' -- A 'WebRequest' object to be invoked when the button is 1664 clicked. 1665 1666 'css_class' -- The CSS class to use for the button, or 'None'.""" 1667 1668 return make_button_for_url(title, request.AsUrl(), css_class)
1669 1670
1671 -def make_button_for_url(title, url, css_class=None):
1672 """Generate HTML for a button. 1673 1674 Note that the caller is responsible for making sure the resulting 1675 button is placed within a form element. 1676 1677 'title' -- The button label. 1678 1679 'url' -- The URL to load when the button is clicked.. 1680 1681 'css_class' -- The CSS class to use for the button, or 'None'.""" 1682 1683 if css_class is None: 1684 class_attribute = "" 1685 else: 1686 class_attribute = 'class="%s"' % css_class 1687 1688 return ''' 1689 <input type="button" %s 1690 value=" %s " 1691 onclick="location = '%s';"/> 1692 ''' % (class_attribute, title, url)
1693 1694
1695 -def get_session(request, session_id):
1696 """Retrieve the session corresponding to 'session_id'. 1697 1698 'request' -- A 'WebRequest' object for which to get the session. 1699 1700 raises -- 'InvalidSessionError' if the session ID is invalid, or is 1701 invalid for this 'request'.""" 1702 1703 # Now's as good a time as any to clean up expired sessions. 1704 __clean_up_expired_sessions() 1705 1706 try: 1707 # Obtain the session for this ID. 1708 session = sessions[session_id] 1709 except KeyError: 1710 # No session for this ID (note that it may have expired). 1711 raise InvalidSessionError, qm.error("session invalid") 1712 # Make sure the session is valid for this request. 1713 session.Validate(request) 1714 # Update the last access time. 1715 session.Touch() 1716 return session
1717 1718
1720 """Remove any sessions that are expired.""" 1721 1722 for session_id, session in sessions.items(): 1723 if session.IsExpired(): 1724 del sessions[session_id]
1725 1726
1727 -def handle_login(request, default_redirect_url="/"):
1728 """Handle a login request. 1729 1730 Authenticate the login using the user name and password stored in 1731 the '_login_user_name' and '_login_password' request fields, 1732 respectively. 1733 1734 If authentication succeeds, redirect to the URL stored in the 1735 '_redirect_url' request field by raising an 'HttpRedirect', passing 1736 all other request fields along as well. 1737 1738 If '_redirect_url' is not specified in the request, the value of 1739 'default_redirect_url' is used instead.""" 1740 1741 # The URL of the page to which to redirect on successful login is 1742 # stored in the request. Extract it. 1743 redirect_url = request.get("_redirect_url", default_redirect_url) 1744 1745 try: 1746 user_id = qm.user.authenticator.AuthenticateWebRequest(request) 1747 except qm.user.AuthenticationError: 1748 # Incorrect user name or password. Show the login form. 1749 message = qm.error("invalid login") 1750 redirect_request = WebRequest(redirect_url) 1751 return generate_login_form(redirect_request, message) 1752 except qm.user.AccountDisabledError: 1753 # Log in to a disabled account. Show the login form again. 1754 message = qm.error("disabled account") 1755 redirect_request = WebRequest(redirect_url) 1756 return generate_login_form(redirect_request, message) 1757 1758 # Check if there is currently a session open for the same user ID. 1759 for session in sessions.values(): 1760 if session.GetUserId() == user_id: 1761 # Yup. There should be only one session at a time for any 1762 # given user. Close that session. 1763 del sessions[session.GetId()] 1764 1765 session = Session(request, user_id) 1766 session_id = session.GetId() 1767 1768 # Generate a new request for that URL. Copy other fields from the 1769 # old request. 1770 redirect_request = request.copy(redirect_url) 1771 # Sanitize the request by removing the user name, password, and 1772 # redirecting URL. 1773 del redirect_request["_login_user_name"] 1774 del redirect_request["_login_password"] 1775 if redirect_request.has_key("_redirect_url"): 1776 del redirect_request["_redirect_url"] 1777 # Add the ID of the new session to the request. 1778 redirect_request.SetSessionId(session_id) 1779 # Redirect the client to the URL for the redirected page. 1780 raise HttpRedirect, redirect_request
1781 1782
1783 -def handle_logout(request, default_redirect_url="/"):
1784 """Handle a logout request. 1785 1786 prerequisite -- 'request' must be in a valid session, which is 1787 ended. 1788 1789 After ending the session, redirect to the URL specified by the 1790 '_redirect_url' field of 'request'. If '_redirect_url' is not 1791 specified in the request, the value of 'default_redirect_url' is 1792 used instead.""" 1793 1794 # Delete the session. 1795 session_id = request.GetSessionId() 1796 del sessions[session_id] 1797 # Construct a redirecting URL. The target is contained in the 1798 # '_redirect_url' field. 1799 redirect_url = request.get("_redirect_url", default_redirect_url) 1800 redirect_request = request.copy(redirect_url) 1801 if redirect_request.has_key("_redirect_url"): 1802 del redirect_request["_redirect_url"] 1803 del redirect_request[session_id_field] 1804 # Redirect to the specified request. 1805 raise HttpRedirect, redirect_request
1806 1807
1808 -def generate_error_page(request, error_text):
1809 """Generate a page to indicate a user error. 1810 1811 'request' -- The request that was being processed when the error 1812 was encountered. 1813 1814 'error_text' -- A description of the error, as structured text. 1815 1816 returns -- The generated HTML source for the page.""" 1817 1818 page = DtmlPage.default_class("error.dtml", error_text=error_text) 1819 return page(request)
1820 1821
1822 -def generate_login_form(redirect_request, message=None):
1823 """Show a form for user login. 1824 1825 'message' -- If not 'None', a message to display to the user.""" 1826 1827 page = DtmlPage.default_class( 1828 "login_form.dtml", 1829 message=message, 1830 default_user_id=qm.user.database.GetDefaultUserId()) 1831 return page(redirect_request)
1832 1833
1834 -def make_set_control(form_name, 1835 field_name, 1836 add_page, 1837 select_name=None, 1838 initial_elements=[], 1839 request=None, 1840 rows=6, 1841 width=200, 1842 window_width=480, 1843 window_height=240, 1844 ordered=0):
1845 """Construct a control for representing a set of items. 1846 1847 'form_name' -- The name of form in which the control is included. 1848 1849 'field_name' -- The name of the input control that contains an 1850 encoded representation of the set's elements. See 1851 'encode_set_control_contents' and 'decode_set_control_contents'. 1852 1853 'select_name' -- The name of the select control that displays the 1854 elements of the set. If 'None', a control name is generated 1855 automatically. 1856 1857 'add_page' -- The URL for a popup web page that is displayed 1858 in response to the "Add..." button. 1859 1860 'initial_elements' -- The initial elements of the set. 1861 1862 'rows' -- The number of rows for the select control. 1863 1864 'width' -- The width of the select control. 1865 1866 'window_width', 'window_height' -- The width and height of the popup 1867 window for adding a new element. 1868 1869 'ordered' -- If true, controls are included for specifying the order 1870 of elements in the set.""" 1871 1872 # Generate a name for the select control if none was specified. 1873 if select_name is None: 1874 select_name = "_set_" + field_name 1875 1876 # Construct the select control. 1877 select = '<select name="%s" size="%d" width="%d">\n' \ 1878 % (select_name, rows, width) 1879 # Add an option for each initial element. 1880 for text, value in initial_elements: 1881 select = select + \ 1882 '<option value="%s">%s</option>\n' % (value, escape(text)) 1883 select = select + '</select>\n' 1884 1885 # Construct the hidden control contianing the set's elements. Its 1886 # initial value is the encoding of the initial elements. 1887 initial_values = map(lambda x: x[1], initial_elements) 1888 initial_value = encode_set_control_contents(initial_values) 1889 contents = '<input type="hidden" name="%s" value="%s"/>' \ 1890 % (field_name, initial_value) 1891 1892 buttons = [] 1893 1894 # Construct the "Add..." button. 1895 buttons.append(make_button_for_popup("Add...", add_page, 1896 window_width, window_height)) 1897 # Construct the "Remove" button. 1898 buttons.append(''' 1899 <input type="button" 1900 size="12" 1901 value=" Remove " 1902 onclick="remove_from_set(document.%s.%s, document.%s.%s);" 1903 />''' % (form_name, select_name, form_name, field_name)) 1904 1905 if ordered: 1906 buttons.append(''' 1907 <input type="button" 1908 size="12" 1909 value=" Move Up " 1910 onclick="move_in_set(document.%s.%s, document.%s.%s, -1);" 1911 />''' % (form_name, select_name, form_name, field_name)) 1912 buttons.append(''' 1913 <input type="button" 1914 size="12" 1915 value=" Move Down " 1916 onclick="move_in_set(document.%s.%s, document.%s.%s, 1);" 1917 />''' % (form_name, select_name, form_name, field_name)) 1918 1919 # Arrange everything in a table to control the layout. 1920 return contents + ''' 1921 <table border="0" cellpadding="0" cellspacing="0"><tbody> 1922 <tr valign="top"> 1923 <td> 1924 %s 1925 </td> 1926 <td>&nbsp;</td> 1927 <td> 1928 %s 1929 </td> 1930 </tr> 1931 </tbody></table> 1932 ''' % (select, string.join(buttons, "<br />"))
1933 1934
1935 -def encode_set_control_contents(values):
1936 """Encode 'values' for a set control. 1937 1938 'values' -- A sequence of values of elements of the set. 1939 1940 returns -- The encoded value for the control field.""" 1941 1942 return string.join(values, ",")
1943 1944
1945 -def decode_set_control_contents(content_string):
1946 """Decode the contents of a set control. 1947 1948 'content_string' -- The text of the form field containing the 1949 encoded set contents. 1950 1951 returns -- A sequence of the values of the elements of the set.""" 1952 1953 # Oddly, if the set is empty, there are sometimes spurious spaces in 1954 # field entry. This may be browser madness. Handle it specially. 1955 if string.strip(content_string) == "": 1956 return [] 1957 return string.split(content_string, ",")
1958 1959
1960 -def make_properties_control(form_name, 1961 field_name, 1962 properties, 1963 select_name=None):
1964 """Construct a control for representing a set of properties. 1965 1966 'form_name' -- The name of form in which the control is included. 1967 1968 'field_name' -- The name of the input control that contains an 1969 encoded representation of the properties. See 'encode_properties' 1970 and 'decode_properties'. 1971 1972 'properties' -- A map from property names to values of the 1973 properties to include in the control initially. 1974 1975 'select_name' -- The name of the select control that displays the 1976 elements of the set. If 'None', a control name is generated 1977 automatically.""" 1978 1979 # Generate a name for the select control if none was specified. 1980 if select_name is None: 1981 select_name = "_propsel_" + field_name 1982 name_control_name = "_propname_" + field_name 1983 value_control_name = "_propval_" + field_name 1984 add_change_button_name = "_propaddedit_" + field_name 1985 1986 # Construct the select control. 1987 select = ''' 1988 <select name="%s" 1989 size="6" 1990 width="240" 1991 onchange="property_update_selection(document.%s.%s, 1992 document.%s.%s, 1993 document.%s.%s); 1994 document.%s.%s.value = ' Change ';" 1995 >\n''' \ 1996 % (select_name, form_name, select_name, 1997 form_name, name_control_name, form_name, value_control_name, 1998 form_name, add_change_button_name) 1999 # Add an option for each initial property. 2000 keys = properties.keys() 2001 keys.sort() 2002 for k in keys: 2003 select = select + \ 2004 '<option value="%s=%s">%s = %s</option>\n' \ 2005 % (k, properties[k], k, properties[k]) 2006 select = select + '</select>\n' 2007 2008 # Construct the hidden control contianing the set's elements. Its 2009 # initial value is the encoding of the initial elements. 2010 initial_value = encode_properties(properties) 2011 contents = '<input type="hidden" name="%s" value="%s"/>' \ 2012 % (field_name, initial_value) 2013 2014 # Construct a control for the property name. 2015 name_control = \ 2016 '''<input type="text" 2017 name="%s" 2018 size="32" 2019 onkeydown="document.%s.%s.value = ' Add ';" 2020 />''' % (name_control_name, form_name, add_change_button_name) 2021 # Construct a control for the property value. 2022 value_control = '<input type="text" name="%s" size="32"/>' \ 2023 % value_control_name 2024 2025 vars = { 'form' : form_name, 2026 'button' : add_change_button_name, 2027 'select' : select_name, 2028 'field' : field_name, 2029 'name' : name_control_name, 2030 'value' : value_control_name } 2031 2032 # Construct the "Change" button. When it's clicked, call 2033 # 'property_update', passing the select control and the hidden 2034 # control whose value should be updated with the new encoded 2035 # property list. 2036 add_change_button = \ 2037 '''<input type="button" 2038 name="%(button)s" 2039 size="12" 2040 value=" Add " 2041 onclick="property_add_or_change 2042 (document.%(form)s.%(select)s, 2043 document.%(form)s.%(field)s, 2044 document.%(form)s.%(name)s, 2045 document.%(form)s.%(value)s);" 2046 />''' % vars 2047 2048 # Construct the "Remove" button. 2049 remove_button = \ 2050 '''<input type="button" 2051 size="12" 2052 value=" Remove " 2053 onclick="property_remove(document.%(form)s.%(select)s, 2054 document.%(form)s.%(field)s, 2055 document.%(form)s.%(name)s, 2056 document.%(form)s.%(value)s, 2057 document.%(form)s.%(button)s);" 2058 />''' % vars 2059 2060 # Arrange everything in a table to control the layout. 2061 return contents + ''' 2062 <table border="0" cellpadding="0" cellspacing="0"><tbody> 2063 <tr valign="top"> 2064 <td colspan="2" width="240">%s</td> 2065 <td>&nbsp;</td> 2066 <td>%s</td> 2067 </tr> 2068 <tr> 2069 <td>Name:&nbsp;</td> 2070 <td align="right">%s </td> 2071 <td>&nbsp;</td> 2072 <td>%s</td> 2073 </tr> 2074 <tr> 2075 <td>Value:&nbsp;</td> 2076 <td align="right">%s </td> 2077 <td>&nbsp;</td> 2078 <td>&nbsp;</td> 2079 </tr> 2080 </tbody></table> 2081 ''' % (select, remove_button, name_control, add_change_button, 2082 value_control)
2083 2084
2085 -def encode_properties(properties):
2086 """Construct a URL-encoded representation of a set of properties. 2087 2088 'properties' -- A map from property names to values. Names must be 2089 URL-safe strings. Values are arbitrary strings. 2090 2091 returns -- A URL-encoded string representation of 'properties'. 2092 2093 This function is the inverse of 'decode_properties'.""" 2094 2095 # Construct a list of property assignment strings. The RHS is 2096 # URL-quoted. 2097 result = map(lambda p: "%s=%s" % (p[0], urllib.quote_plus(p[1])), 2098 properties.items()) 2099 # Join them into a comma-delimited list. 2100 return string.join(result, ",")
2101 2102
2103 -def decode_properties(properties):
2104 """Decode a URL-encoded representation of a set of properties. 2105 2106 'properties' -- A string containing URL-encoded properties. 2107 2108 returns -- A map from names to values. 2109 2110 This function is the inverse of 'encode_properties'.""" 2111 2112 properties = string.strip(properties) 2113 # Empty? 2114 if properties == "": 2115 return {} 2116 2117 # The string is a comma-delimited list. Split it up. 2118 properties = string.split(properties, ",") 2119 # Convert to a map, processing each item. 2120 result = {} 2121 for assignment in properties: 2122 # Each element is a "name=value" assignment. Split it up. 2123 name, value = string.split(assignment, "=") 2124 # The value is URL-quoted. Unquote it. 2125 value = urllib.unquote_plus(value) 2126 # Set it in the map. 2127 result[name] = value 2128 2129 return result
2130 2131
2132 -def make_javascript_string(text):
2133 """Return 'text' represented as a JavaScript string literal.""" 2134 2135 text = string.replace(text, "\\", r"\\") 2136 text = string.replace(text, "'", r"\'") 2137 text = string.replace(text, "\"", r'\"') 2138 text = string.replace(text, "\n", r"\n") 2139 # Escape less-than signs so browsers don't look for HTML tags 2140 # inside the literal. 2141 text = string.replace(text, "<", r"\074") 2142 return "'" + text + "'"
2143 2144 2162 2163 2195 2196
2197 -def make_popup_page(message, buttons, title=""):
2198 """Generate a popup dialog box page. 2199 2200 See 'make_popup_dialog_script' for an explanation of the 2201 parameters.""" 2202 2203 page = \ 2204 '''<html> 2205 <head> 2206 <title>%s</title> 2207 <meta http-equiv="Content-Style-Type" content="text/css"/> 2208 <link rel="stylesheet" type="text/css" href="/stylesheets/qm.css"/> 2209 </head> 2210 <body class="popup"> 2211 <table border="0" cellpadding="0" cellspacing="8" width="100%%"> 2212 <tr><td> 2213 %s 2214 </td></tr> 2215 <tr><td align="right"> 2216 <form name="navigation"> 2217 ''' % (title, message) 2218 # Generate the buttons. 2219 for caption, script in buttons: 2220 page = page + ''' 2221 <input type="button" 2222 value=" %s "''' % caption 2223 # Whether a script was specified for the button, close the popup 2224 # window. 2225 if script is None: 2226 page = page + ''' 2227 onclick="window.close();"''' 2228 else: 2229 page = page + ''' 2230 onclick="%s; window.close();"''' % script 2231 page = page + ''' 2232 />''' 2233 # End the page. 2234 page = page + ''' 2235 </form> 2236 </td></tr> 2237 </table> 2238 </body> 2239 </html> 2240 ''' 2241 return page
2242 2243
2244 -def make_choose_control(field_name, 2245 included_label, 2246 included_items, 2247 excluded_label, 2248 excluded_items, 2249 item_to_text=str, 2250 item_to_value=str, 2251 ordered=0):
2252 """Construct HTML controls for selecting a subset. 2253 2254 The user is presented with two list boxes next to each other. The 2255 box on the left lists items included in the subset. The box on the 2256 right lists items excluded from the subset but available for 2257 inclusion. Between the boxes are buttons for adding and removing 2258 items from the subset. 2259 2260 If 'ordered' is true, buttons are also shown for reordering items in 2261 the included list. 2262 2263 'field_name' -- The name of an HTML hidden form field that will 2264 contain an encoding of the items included in the subset. The 2265 encoding consists of the values corresponding to included items, in 2266 a comma-separated list. 2267 2268 'included_label' -- HTML source for the label for the left box, 2269 which displays the included items. 2270 2271 'included_items' -- Items initially included in the subset. This is 2272 a sequence of arbitrary objects or values. 2273 2274 'excluded_label' -- HTML source for the label for the right box, 2275 which displays the items available for inclusion but not currently 2276 included. 2277 2278 'excluded_items' -- Items not initially included but available for 2279 inclusion. This is a sequence of arbitrary objects or values. 2280 2281 'item_to_text' -- A function that produces a user-visible text 2282 description of an item. 2283 2284 'item_to_value' -- A function that produces a value for an item, 2285 used as the value for an HTML option object. 2286 2287 'ordered' -- If true, additional controls are displayed to allow the 2288 user to manipulate the order of items in the included set. 2289 2290 returns -- HTML source for the items. Must be placed in a 2291 form.""" 2292 2293 # We'll construct an array of buttons. Each element is an HTML 2294 # input control. 2295 buttons = [] 2296 # Construct the encoding for the items initially included. 2297 initial_value = string.join(map(item_to_value, included_items), ",") 2298 # The hidden control that will contain the encoded representation of 2299 # the included items. 2300 hidden_control = '<input type="hidden" name="%s" value="%s">' \ 2301 % (field_name, initial_value) 2302 # Construct names for the two select controls. 2303 included_select_name = "_inc_" + field_name 2304 excluded_select_name = "_exc_" + field_name 2305 2306 # The select control for included items. When the user selects an 2307 # item in this list, deselect the selected item in the excluded 2308 # list, if any. 2309 included_select = ''' 2310 <select name="%s" 2311 width="160" 2312 size="8" 2313 onchange="document.form.%s.selectedIndex = -1;">''' \ 2314 % (included_select_name, excluded_select_name) 2315 # Build options for items initially selected. 2316 for item in included_items: 2317 option = '<option value="%s">%s</option>\n' \ 2318 % (item_to_value(item), item_to_text(item)) 2319 included_select = included_select + option 2320 included_select = included_select + '</select>\n' 2321 2322 # The select control for excluded items. When the user selects an 2323 # item in this list, deselect the selected item in the included 2324 # list, if any. 2325 excluded_select = ''' 2326 <select name="%s" 2327 width="160" 2328 size="8" 2329 onchange="document.form.%s.selectedIndex = -1;">''' \ 2330 % (excluded_select_name, included_select_name) 2331 # Build options for items initially excluded. 2332 for item in excluded_items: 2333 option = '<option value="%s">%s</option>\n' \ 2334 % (item_to_value(item), item_to_text(item)) 2335 excluded_select = excluded_select + option 2336 excluded_select = excluded_select + '</select>\n' 2337 2338 # The Add button. 2339 button = ''' 2340 <input type="button" 2341 value=" << Add " 2342 onclick="move_option(document.form.%s, document.form.%s); 2343 document.form.%s.value = 2344 encode_select_options(document.form.%s);" /> 2345 ''' % (excluded_select_name, included_select_name, 2346 field_name, included_select_name) 2347 buttons.append(button) 2348 2349 # The Remove button. 2350 button = ''' 2351 &nbsp;<input 2352 type="button" 2353 value=" Remove >> " 2354 onclick="move_option(document.form.%s, document.form.%s); 2355 document.form.%s.value = 2356 encode_select_options(document.form.%s);" />&nbsp; 2357 ''' % (included_select_name, excluded_select_name, 2358 field_name, included_select_name) 2359 buttons.append(button) 2360 2361 if ordered: 2362 # The Move Up button. 2363 button = ''' 2364 <input type="button" 2365 value=" Move Up " 2366 onclick="swap_option(document.form.%s, -1); 2367 document.form.%s.value = 2368 encode_select_options(document.form.%s);"/> 2369 ''' % (included_select_name, field_name, included_select_name) 2370 2371 buttons.append(button) 2372 2373 # The Move Down button. 2374 button = ''' 2375 <input type="button" 2376 value=" Move Down " 2377 onclick="swap_option(document.form.%s, 1); 2378 document.form.%s.value = 2379 encode_select_options(document.form.%s);"/> 2380 ''' % (included_select_name, field_name, included_select_name) 2381 buttons.append(button) 2382 2383 # Arrange everything properly. 2384 buttons = string.join(buttons, "\n<br />\n") 2385 return ''' 2386 %(hidden_control)s 2387 <table border="0" cellpadding="0" cellspacing="0"> 2388 <tr valign="center"> 2389 <td> 2390 %(included_label)s: 2391 <br /> 2392 %(included_select)s 2393 </td> 2394 <td align="center"> 2395 %(buttons)s 2396 </td> 2397 <td> 2398 %(excluded_label)s:<br /> 2399 %(excluded_select)s 2400 </td> 2401 </tr> 2402 </table> 2403 ''' % locals()
2404 2405
2406 -def make_button_for_popup(label, 2407 url, 2408 window_width=480, 2409 window_height=240):
2410 """Construct a button for displaying a popup page. 2411 2412 'label' -- The button label. 2413 2414 'url' -- The URL to display in the popup page. 2415 2416 returns -- HTML source for the button. The button must be placed 2417 within a form element.""" 2418 2419 # Construct arguments for 'Window.open'. 2420 window_args = "resizable,width=%d,height=%s" \ 2421 % (window_width, window_height) 2422 # Generate it. 2423 return """ 2424 <input type="button" 2425 value=" %(label)s " 2426 onclick="window.open('%(url)s', 2427 'popup', 2428 '%(window_args)s');"> 2429 """ % locals()
2430 2431
2432 -def format_color(red, green, blue):
2433 """Format an RGB color value for HTML. 2434 2435 'red', 'green', 'blue' -- Color values for respective channels, 2436 between 0.0 and 1.0. Values outside this range are truncated to 2437 this range.""" 2438 2439 # Manual loop unrolling, for efficiency. 2440 red = int(256 * red) 2441 if red < 0: 2442 red = 0 2443 if red > 255: 2444 red = 255 2445 green = int(256 * green) 2446 if green < 0: 2447 green = 0 2448 if green > 255: 2449 green = 255 2450 blue = int(256 * blue) 2451 if blue < 0: 2452 blue = 0 2453 if blue > 255: 2454 blue = 255 2455 return "#%02x%02x%02x" % (red, green, blue)
2456 2457
2458 -def javascript_escape(text):
2459 """Equivalent to the JavaScript 'escape' built-in function.""" 2460 2461 text = urllib.quote(text) 2462 text = string.replace(text, ",", "%2C") 2463 return text
2464 2465
2466 -def javascript_unescape(text):
2467 """Equivalent to the JavaScript 'unescape' built-in function.""" 2468 2469 return urllib.unquote(text)
2470 2471
2472 -def make_submit_button(title="OK"):
2473 """Generate HTML for a button to submit the current form. 2474 2475 'title' -- The button title.""" 2476 2477 return ''' 2478 <input type="button" 2479 class="submit" 2480 value=" %s " 2481 onclick="submit();" 2482 />''' % title
2483 2484 2485 ######################################################################## 2486 # variables 2487 ######################################################################## 2488 2489 sessions = {} 2490 """A mapping from session IDs to 'Session' instances.""" 2491 2492 _counter = 0 2493 """A counter for generating somewhat-unique names.""" 2494 2495 _page_cache_name = "page-cache" 2496 """The URL prefix for the global page cache.""" 2497 2498 _session_cache_name = "session-cache" 2499 """The URL prefix for the session page cache.""" 2500 2501 ######################################################################## 2502 # Local Variables: 2503 # mode: python 2504 # indent-tabs-mode: nil 2505 # fill-column: 72 2506 # End: 2507

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python-pysrc.html0000664000076400007640000032646011122067154026401 0ustar stefanstefan qm.test.classes.python
Package qm :: Package test :: Package classes :: Module python
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.python

  1  ######################################################################## 
  2  # 
  3  # File:   python.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-04-03 
  6  # 
  7  # Contents: 
  8  #   Test classes for tests written in Python. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  """Test classes for tests written in Python.""" 
 17   
 18  ######################################################################## 
 19  # imports 
 20  ######################################################################## 
 21   
 22  import qm 
 23  import qm.fields 
 24  import qm.test.base 
 25  from   qm.test.result import * 
 26  from   qm.test.test import * 
 27  import string 
 28  import sys 
 29  import types 
 30   
 31  ######################################################################## 
 32  # classes 
 33  ######################################################################## 
 34   
35 -class ExecTest(Test):
36 """Check that a Python expression evaluates to true. 37 38 An 'ExecTest' test consists of Python source code together with 39 an (optional) Python expression. First the Python code is 40 executed. If it throws an (uncaught) exception the test fails. 41 If the optional expression is present, it is then evaluated. If it 42 evaluates to false, the test fails. Otherwise, the test passes.""" 43 44 arguments = [ 45 qm.fields.TextField( 46 name="source", 47 title="Python Source Code", 48 description="""The source code. 49 50 This code may contain class definitions, function 51 definitions, statements, and so forth. If this code 52 throws an uncaught exception, the test will fail.""", 53 verbatim="true", 54 multiline="true", 55 default_value="pass" 56 ), 57 58 qm.fields.TextField( 59 name="expression", 60 title="Python Expression", 61 description="""The expression to evaluate. 62 63 If the expression evaluates to true, the test will pass, 64 unless the source code above throws an uncaught exception. 65 66 If this field is left blank, it is treated as an expression 67 that is always true.""", 68 verbatim="true", 69 multiline="true", 70 default_value="1" 71 ) 72 ] 73 74
75 - def Run(self, context, result):
76 77 # Adjust the source code. Make sure the source ends with a 78 # newline. A user is likely to be confused by the error message 79 # if it's missing. 80 if not self.source: 81 self.source = "\n" 82 elif self.source[-1] != "\n": 83 self.source += "\n" 84 global_namespace, local_namespace = make_namespaces(context) 85 # Execute the source code. 86 try: 87 exec self.source in global_namespace, local_namespace 88 except: 89 # The source raised an unhandled exception, so the test 90 # fails 91 result.NoteException(cause="Exception executing source.") 92 else: 93 # The source code executed OK. Was an additional expression 94 # provided? 95 if self.expression is not None: 96 # Yes; evaluate it. 97 try: 98 value = eval(self.expression, 99 global_namespace, local_namespace) 100 except: 101 # Oops, an exception while evaluating the 102 # expression. The test fails. 103 result.NoteException(cause= 104 "Exception evaluating expression.") 105 else: 106 # We evaluated the expression. The test passes iff 107 # the expression's value is boolean true. 108 if not value: 109 result.Fail("Expression evaluates to false.", 110 { "ExecTest.expr" : self.expression, 111 "ExecTest.value" : repr(value) }) 112 else: 113 # No expression provided; if we got this far, the test 114 # passes. 115 pass
116 117
118 -class BaseExceptionTest(Test):
119 """Base class for tests of exceptions.""" 120 121 arguments = [ 122 qm.fields.TextField( 123 name="source", 124 title="Python Source Code", 125 description="""The source code. 126 127 This code may contain class definitions, function 128 definitions, statements, and so forth.""", 129 verbatim="true", 130 multiline="true", 131 default_value="pass" 132 ), 133 134 qm.fields.TextField( 135 name="exception_argument", 136 title="Exception Argument", 137 description="""The expected value of the exception. 138 139 This value is a Python expression which should evaluate 140 to the same value as the exception raised. 141 142 If this field is left blank, the value of the exception is 143 ignored.""", 144 default_value="" 145 ) 146 ] 147 148
149 - def Run(self, context, result):
150 151 # Adjust the exception argument. 152 if string.strip(self.exception_argument) != "": 153 self.exception_argument = eval(self.exception_argument, {}, {}) 154 self.has_exception_argument = 1 155 else: 156 self.has_exception_argument = 0 157 158 global_namespace, local_namespace = make_namespaces(context) 159 try: 160 # Execute the test code. 161 exec self.source in global_namespace, local_namespace 162 except: 163 exc_info = sys.exc_info() 164 # Check the exception argument. 165 self.CheckArgument(exc_info, result) 166 if result.GetOutcome() != Result.PASS: 167 return 168 # Check that the exception itself is OK. 169 self.MakeResult(exc_info, result) 170 else: 171 # The test code didn't raise an exception. 172 result.Fail(qm.message("test did not raise"))
173 174
175 - def CheckArgument(self, exc_info, result):
176 """Check that the exception argument matches expectations. 177 178 'result' -- The result object for this test.""" 179 180 # Was an expected exception argument specified? 181 if self.has_exception_argument: 182 # Yes. Extract the exception argument. 183 argument = exc_info[1] 184 if cmp(argument, self.exception_argument): 185 cause = qm.message("test raised wrong argument") 186 result.Fail(cause, 187 { "BaseExceptionTest.type" : 188 str(exc_info[0]), 189 "BaseExceptionTest.argument" : 190 repr(argument) })
191 192
193 - def MakeResult(self, exc_info, result):
194 """Check the exception in 'exc_info' and construct the result. 195 196 'result' -- The result object for this test.""" 197 198 pass
199 200 201
202 -class ExceptionTest(BaseExceptionTest):
203 """Check that the specified Python code raises an exception. 204 205 An 'ExceptionTest' checks that the specified Python code raises a 206 particular exception. The test passes if the exception is an 207 instance of the expected class and (optionally) if its value matches 208 the expected value. If the code fails to raise an exception, the 209 test fails.""" 210 211 arguments = [ 212 qm.fields.TextField( 213 name="exception_class", 214 title="Exception Class", 215 description="""The expected type of the exception. 216 217 This value is the name of a Python class. If the 218 exception raised is not an instance of this class, the 219 test fails.""", 220 default_value="Exception" 221 ) 222 ] 223 224
225 - def MakeResult(self, exc_info, result):
226 # Make sure the exception is an object. 227 if not type(exc_info[0]) in [types.ClassType, type]: 228 result.Fail(qm.message("test raised non-object", 229 exc_type=str(type(exc_info[0])))) 230 # Make sure it's an instance of the right class. 231 exception_class_name = exc_info[0].__name__ 232 if exception_class_name != self.exception_class: 233 cause = qm.message("test raised wrong class", 234 class_name=exception_class_name) 235 result.Fail(cause=cause)
236 237
238 - def CheckArgument(self, exc_info, result):
239 """Check that the exception argument matches expectations. 240 241 'result' -- The result object for this test.""" 242 243 # Was an expected argument specified? 244 if self.has_exception_argument: 245 # Extract the actual argument from the exception object. 246 try: 247 argument = exc_info[1].args 248 except: 249 # If the "args" were not available, then the exception 250 # object does not use the documented interface given 251 # for Exception. 252 result.Fail("Exception object does not provide access " 253 "to arguments provided to 'raise'", 254 { "ExceptionTest.type" : str(exc_info[0]) }) 255 return 256 257 # Now the expected argument. 258 expected_argument = self.exception_argument 259 # Python wraps the arguments to class exceptions in strange 260 # ways, so wrap the expected argument similarly. A 'None' 261 # argument is represented by an empty tuple. 262 if expected_argument is None: 263 expected_argument = () 264 # Tuple arguments are unmodified. 265 elif type(expected_argument) is types.TupleType: 266 pass 267 # A non-tuple argument is wrapped in a tuple. 268 else: 269 expected_argument = (expected_argument, ) 270 271 # Compare the actual argument to the expectation. 272 if cmp(expected_argument, argument) != 0: 273 # We got a different argument. The test fails. 274 cause = qm.message("test raised wrong argument") 275 result.Fail(cause, 276 { "ExceptionTest.type" : str(exc_info[0]), 277 "ExceptionTest.argument" : repr(argument) })
278 279 280
281 -class StringExceptionTest(BaseExceptionTest):
282 """Check that the specified Python code raises a string exception. 283 284 A 'StringExceptionTest' checks that the specified code throws 285 an exception. The exception must be a string and must have 286 the expected value.""" 287 288 arguments = [ 289 qm.fields.TextField( 290 name="exception_text", 291 title="Exception Text", 292 description="The expected exception string.", 293 default_value="exception" 294 ) 295 ] 296 297
298 - def MakeResult(self, exc_info, result):
299 # Make sure the exception is an object. 300 if not type(exc_info[0]) is types.StringType: 301 result.Fail(qm.message("test raised non-string", 302 exc_type=str(type(exc_info[0])))) 303 # Make sure it's the right string. 304 if exc_info[0] != self.exception_text: 305 result.Fail(qm.message("test raised wrong string", 306 text=exc_info[0]))
307 308 309 310 ######################################################################## 311 # functions 312 ######################################################################## 313
314 -def make_namespaces(context):
315 """Construct namespaces for eval/exec of Python test code. 316 317 'context' -- The test context. 318 319 returns -- A pair '(global_namespace, local_namespace)' of maps.""" 320 321 # The global namespace contains only the context object. 322 global_namespace = { 323 "context": context, 324 } 325 # The local namespace is empty. 326 local_namespace = { 327 } 328 # FIXME: As of 2005-03-21, all python versions I tested with 329 # contain a bug that makes non-trivial code fail when 330 # global_namespace != local_namespace. See bug #1167300 331 # 332 # Meanwhile, we use the global namespace for both, which 333 # yields the same as when calling 'exec source in globals()' 334 335 #return global_namespace, local_namespace 336 return global_namespace, global_namespace
337 338 339 ######################################################################## 340 # Local Variables: 341 # mode: python 342 # indent-tabs-mode: nil 343 # fill-column: 72 344 # End: 345

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.DefaultDtmlPage-class.html0000664000076400007640000006532111122067151027714 0ustar stefanstefan qm.test.web.web.DefaultDtmlPage
Package qm :: Package test :: Package web :: Module web :: Class DefaultDtmlPage
[hide private]
[frames] | no frames]

Class DefaultDtmlPage

source code

web.DtmlPage --+
               |
              DefaultDtmlPage

Subclass of DTML page class for QMTest pages.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, dtml_template, server, **attributes)
Construct a new 'QMTestPage'.
source code
 
GetName(self)
Return the name of the application.
source code
 
MakeListingUrl(self) source code
 
GetMainPageUrl(self)
Return the URL for the main page.
source code
 
GetDatabase(self)
Returns the 'Database' in use.
source code
 
IsLabelInDirectory(self, id, directory)
Returns true if 'id' is in 'directory'.
source code
 
FormatId(self, id, type, style="basic")
Format 'id' as HTML.
source code
 
GetResultsByOutcome(self, results)
Compute the tests in 'results' with each outcome.
source code
 
GetOutcomePercentages(self, results)
Compute the percentage (by outcome) of the 'results'.
source code
 
HasModifiableExpectations(self)
Return True if expectations are modifiable.
source code

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateHtmlHeader, GenerateStartBody, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]
  html_generator = "QMTest"
  NEGATIVE_UNEXPECTED = 'FAIL'
A test's result was unfavorably unexpected.
  POSITIVE_UNEXPECTED = 'PASS'
A test's result was favorably unexpected.
  EXPECTED = "EXPECTED"
A test's result was as expected.
  EXPECTATION_KINDS = [NEGATIVE_UNEXPECTED, EXPECTED, POSITIVE_U...
The kinds of expectations.
  outcomes = Result.outcomes+ [EXPECTED]

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, dtml_template, server, **attributes)
(Constructor)

source code 

Construct a new 'QMTestPage'.

'server' -- The 'QMTestServer' creating this page.

'dtml_template' -- The file name of the DTML template, relative to the DTML directory.

Overrides: web.DtmlPage.__init__

GetMainPageUrl(self)

source code 

Return the URL for the main page.

Overrides: web.DtmlPage.GetMainPageUrl
(inherited documentation)

GetDatabase(self)

source code 

Returns the 'Database' in use.

returns -- The 'Database' in use.

IsLabelInDirectory(self, id, directory)

source code 

Returns true if 'id' is in 'directory'.

returns -- True if 'id' indicates a test contained in 'directory', or one of its subdirectories.

FormatId(self, id, type, style="basic")

source code 

Format 'id' as HTML.

'id' -- The name of a test or resource.

'type' -- The kind of item named by 'id'. Either 'resource', 'suite', or 'test'.

'style' -- The formatting style to use. One of 'plain', 'basic', 'navigation', or 'tree'.

returns -- A string containing HTML to use for 'id'.

GetResultsByOutcome(self, results)

source code 

Compute the tests in 'results' with each outcome.

'results' -- A sequence of 'Result' instances.

returns -- A dictionary mapping outcomes to the sequence of tests that have the indicated outcome in 'results'.

GetOutcomePercentages(self, results)

source code 

Compute the percentage (by outcome) of the 'results'.

'results' -- A sequence of 'Result' instances.

returns -- A dictionary mapping outcomes to the percentage (as a floating point number) of tests in 'results' that have that outcome.


Class Variable Details [hide private]

EXPECTATION_KINDS

The kinds of expectations.

Value:
[NEGATIVE_UNEXPECTED, EXPECTED, POSITIVE_UNEXPECTED]

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_HTML-module.html0000664000076400007640000000266611122067144031601 0ustar stefanstefan DT_HTML

Module DT_HTML


Classes

HTML
HTMLDefault
HTMLFile
dtml_re_class

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.WebRequestHandler-class.html0000664000076400007640000004363511122067151026550 0ustar stefanstefan qm.web.WebRequestHandler
Package qm :: Module web :: Class WebRequestHandler
[hide private]
[frames] | no frames]

Class WebRequestHandler

source code

SocketServer.BaseRequestHandler --+            
                                  |            
  SocketServer.StreamRequestHandler --+        
                                      |        
  BaseHTTPServer.BaseHTTPRequestHandler --+    
                                          |    
  SimpleHTTPServer.SimpleHTTPRequestHandler --+
                                              |
                                             WebRequestHandler

Handler for HTTP requests.

This class groups callback functions that are invoked in response to HTTP requests by 'WebServer'.

Don't define '__init__' or store any persistent information in this class or subclasses; a new instance is created for each request. Instead, store the information in the server instance, available through the 'server' attribute.

Nested Classes [hide private]

Inherited from BaseHTTPServer.BaseHTTPRequestHandler: MessageClass

Instance Methods [hide private]
 
do_GET(self)
Process HTTP GET requests.
source code
 
do_POST(self)
Process HTTP POST requests.
source code
 
__HandleScriptRequest(self, request) source code
 
__HandleFileRequest(self, request, path) source code
 
__HandlePageCacheRequest(self, request)
Process a retrieval request from the global page cache.
source code
 
__HandleSessionCacheRequest(self, request)
Process a retrieval request from the session page cache.
source code
 
__HandleRequest(self, request)
Process a request from a GET or POST operation.
source code
 
log_message(self, format, *args)
Log a message; overrides 'BaseHTTPRequestHandler.log_message'.
source code

Inherited from SimpleHTTPServer.SimpleHTTPRequestHandler: copyfile, do_HEAD, guess_type, list_directory, send_head, translate_path

Inherited from BaseHTTPServer.BaseHTTPRequestHandler: address_string, date_time_string, end_headers, handle, handle_one_request, log_date_time_string, log_error, log_request, parse_request, send_error, send_header, send_response, version_string

Inherited from SocketServer.StreamRequestHandler: finish, setup

Inherited from SocketServer.BaseRequestHandler: __init__

Class Variables [hide private]

Inherited from SimpleHTTPServer.SimpleHTTPRequestHandler: extensions_map, server_version

Inherited from BaseHTTPServer.BaseHTTPRequestHandler: error_message_format, monthname, protocol_version, responses, sys_version, weekdayname

Inherited from SocketServer.StreamRequestHandler: rbufsize, wbufsize

Method Details [hide private]

do_GET(self)

source code 

Process HTTP GET requests.

Overrides: SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET

__HandleRequest(self, request)

source code 

Process a request from a GET or POST operation.

'request' -- A 'WebRequest' object.

log_message(self, format, *args)

source code 

Log a message; overrides 'BaseHTTPRequestHandler.log_message'.

Overrides: BaseHTTPServer.BaseHTTPRequestHandler.log_message

././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.sql_result_stream.SQLResultReader-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.sql_result_stream.SQLResultReader-class.ht0000664000076400007640000006021411122067147033216 0ustar stefanstefan qm.test.classes.sql_result_stream.SQLResultReader
Package qm :: Package test :: Package classes :: Module sql_result_stream :: Class SQLResultReader
[hide private]
[frames] | no frames]

Class SQLResultReader

source code

            object --+        
                     |        
   extension.Extension --+    
                         |    
result_reader.ResultReader --+
                             |
            object --+       |
                     |       |
   extension.Extension --+   |
                         |   |
             _SQLConnected --+
                             |
                            SQLResultReader

A 'SQLResultReader' reads result in from an SQL database.

This class currently supports PostgreSQL only.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code
 
_LoadAnnotations(self) source code
 
GetAnnotations(self)
Return this run's dictionary of annotations.
source code
 
_SetupResultCursors(self) source code
 
GetResult(self)
Return the next 'Result' from this reader.
source code

Inherited from result_reader.ResultReader: __iter__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.fields.IntegerField'> run_id>]
A list of the arguments to the extension class.
  _argument_dictionary = {'connection': <<class 'qm.fields.Pytho...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.TextField'> db_module>, <...
A list of all the 'Field's in this class.
  run_id = 0

Inherited from result_reader.ResultReader: kind

Inherited from _SQLConnected: connection, db_module, db_name

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

GetAnnotations(self)

source code 

Return this run's dictionary of annotations.

Overrides: result_reader.ResultReader.GetAnnotations
(inherited documentation)

GetResult(self)

source code 

Return the next 'Result' from this reader.

returns -- A 'Result', or 'None' if there are no more results.

Overrides: result_reader.ResultReader.GetResult
(inherited documentation)

Class Variable Details [hide private]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'connection': <<class 'qm.fields.PythonField'> connection>,
 'db_module': <<class 'qm.fields.TextField'> db_module>,
 'db_name': <<class 'qm.fields.TextField'> db_name>,
 'run_id': <<class 'qm.fields.IntegerField'> run_id>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.TextField'> db_module>,
 <<class 'qm.fields.PythonField'> connection>,
 <<class 'qm.fields.TextField'> db_name>,
 <<class 'qm.fields.IntegerField'> run_id>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_String-pysrc.html0000664000076400007640000072770711122067161031404 0ustar stefanstefan qm.external.DocumentTemplate.DT_String
Package qm :: Package external :: Package DocumentTemplate :: Module DT_String
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_String

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  "$Id: DT_String.py 40317 2005-11-22 15:14:40Z tseaver $" 
 14   
 15  import os 
 16  import thread 
 17  import re 
 18   
 19  from DT_Util import ParseError, InstanceDict, TemplateDict, render_blocks, str 
 20  from DT_Var import Var, Call, Comment 
 21  from DT_Return import ReturnTag, DTReturn 
 22   
 23  _marker = []  # Create a new marker object. 
 24   
25 -class String:
26 """Document templates defined from strings. 27 28 Document template strings use an extended form of python string 29 formatting. To insert a named value, simply include text of the 30 form: '%(name)x', where 'name' is the name of the value and 'x' is 31 a format specification, such as '12.2d'. 32 33 To intrduce a block such as an 'if' or an 'in' or a block continuation, 34 such as an 'else', use '[' as the format specification. To 35 terminate a block, ise ']' as the format specification, as in:: 36 37 %(in results)[ 38 %(name)s 39 %(in results)] 40 41 """ 42 43 isDocTemp=1 44 45 # Document Templates masquerade as functions:
46 - class func_code: pass
47 func_code=func_code() 48 func_code.co_varnames='self','REQUEST' 49 func_code.co_argcount=2 50 func_code.__roles__=() 51 52 func_defaults__roles__=() 53 func_defaults=() 54 55 errQuote__roles__=()
56 - def errQuote(self, s): return s
57 58 parse_error__roles__=()
59 - def parse_error(self, mess, tag, text, start):
60 raise ParseError, "%s, for tag %s, on line %s of %s" % ( 61 mess, self.errQuote(tag), len(text[:start].split('\n')), 62 self.errQuote(self.__name__))
63 64 commands__roles__=() 65 commands={ 66 'var': Var, 67 'call': Call, 68 'in': ('in', 'DT_In','In'), 69 'with': ('with', 'DT_With','With'), 70 'if': ('if', 'DT_If','If'), 71 'unless': ('unless', 'DT_If','Unless'), 72 'else': ('else', 'DT_If','Else'), 73 'comment': Comment, 74 'raise': ('raise', 'DT_Raise','Raise'), 75 'try': ('try', 'DT_Try','Try'), 76 'let': ('let', 'DT_Let', 'Let'), 77 'return': ReturnTag, 78 } 79 80 SubTemplate__roles__=()
81 - def SubTemplate(self, name):
82 return String('', __name__=name)
83 84 tagre__roles__=()
85 - def tagre(self):
86 return re.compile( 87 '%\\(' # beginning 88 '(?P<name>[a-zA-Z0-9_/.-]+)' # tag name 89 '(' 90 '[\000- ]+' # space after tag name 91 '(?P<args>([^\\)"]+("[^"]*")?)*)' # arguments 92 ')?' 93 '\\)(?P<fmt>[0-9]*[.]?[0-9]*[a-z]|[]![])' # end 94 , re.I)
95 96 _parseTag__roles__=()
97 - def _parseTag(self, match_ob, command=None, sargs='', tt=type(())):
98 tag, args, command, coname = self.parseTag(match_ob,command,sargs) 99 if type(command) is tt: 100 cname, module, name = command 101 d={} 102 try: 103 exec 'from %s import %s' % (module, name) in d 104 except ImportError: 105 exec 'from DocumentTemplate.%s import %s' % (module, name) in d 106 command=d[name] 107 self.commands[cname]=command 108 return tag, args, command, coname
109 110 parseTag__roles__=()
111 - def parseTag(self, match_ob, command=None, sargs=''):
112 """Parse a tag using an already matched re 113 114 Return: tag, args, command, coname 115 116 where: tag is the tag, 117 args is the tag\'s argument string, 118 command is a corresponding command info structure if the 119 tag is a start tag, or None otherwise, and 120 coname is the name of a continue tag (e.g. else) 121 or None otherwise 122 """ 123 tag, name, args, fmt = match_ob.group(0, 'name', 'args', 'fmt') 124 args=args and args.strip() or '' 125 126 if fmt==']': 127 if not command or name != command.name: 128 raise ParseError, ('unexpected end tag', tag) 129 return tag, args, None, None 130 elif fmt=='[' or fmt=='!': 131 if command and name in command.blockContinuations: 132 133 if name=='else' and args: 134 # Waaaaaah! Have to special case else because of 135 # old else start tag usage. Waaaaaaah! 136 l=len(args) 137 if not (args==sargs or 138 args==sargs[:l] and sargs[l:l+1] in ' \t\n'): 139 return tag, args, self.commands[name], None 140 141 return tag, args, None, name 142 143 try: return tag, args, self.commands[name], None 144 except KeyError: 145 raise ParseError, ('Unexpected tag', tag) 146 else: 147 # Var command 148 args=args and ("%s %s" % (name, args)) or name 149 return tag, args, Var, None
150 151 varExtra__roles__=()
152 - def varExtra(self, match_ob):
153 return match_ob.group('fmt')
154 155 parse__roles__=()
156 - def parse(self,text,start=0,result=None,tagre=None):
157 if result is None: result=[] 158 if tagre is None: tagre=self.tagre() 159 mo = tagre.search(text,start) 160 while mo : 161 l = mo.start(0) 162 163 try: tag, args, command, coname = self._parseTag(mo) 164 except ParseError, m: self.parse_error(m[0],m[1],text,l) 165 166 s=text[start:l] 167 if s: result.append(s) 168 start=l+len(tag) 169 170 if hasattr(command,'blockContinuations'): 171 start=self.parse_block(text, start, result, tagre, 172 tag, l, args, command) 173 else: 174 try: 175 if command is Var: r=command(args, self.varExtra(mo)) 176 else: r=command(args) 177 if hasattr(r,'simple_form'): r=r.simple_form 178 result.append(r) 179 except ParseError, m: self.parse_error(m[0],tag,text,l) 180 181 mo = tagre.search(text,start) 182 183 text=text[start:] 184 if text: result.append(text) 185 return result
186 187 skip_eol__roles__=()
188 - def skip_eol(self, text, start, eol=re.compile('[ \t]*\n')):
189 # if block open is followed by newline, then skip past newline 190 mo =eol.match(text,start) 191 if mo is not None: 192 start = start + mo.end(0) - mo.start(0) 193 194 return start
195 196 parse_block__roles__=()
197 - def parse_block(self, text, start, result, tagre, 198 stag, sloc, sargs, scommand):
199 200 start=self.skip_eol(text,start) 201 202 blocks=[] 203 tname=scommand.name 204 sname=stag 205 sstart=start 206 sa=sargs 207 while 1: 208 209 mo = tagre.search(text,start) 210 if mo is None: self.parse_error('No closing tag', stag, text, sloc) 211 l = mo.start(0) 212 213 try: tag, args, command, coname= self._parseTag(mo,scommand,sa) 214 except ParseError, m: self.parse_error(m[0],m[1], text, l) 215 216 if command: 217 start=l+len(tag) 218 if hasattr(command, 'blockContinuations'): 219 # New open tag. Need to find closing tag. 220 start=self.parse_close(text, start, tagre, tag, l, 221 command, args) 222 else: 223 # Either a continuation tag or an end tag 224 section=self.SubTemplate(sname) 225 section._v_blocks=section.blocks=self.parse(text[:l],sstart) 226 section._v_cooked=None 227 blocks.append((tname,sargs,section)) 228 229 start=self.skip_eol(text,l+len(tag)) 230 231 if coname: 232 tname=coname 233 sname=tag 234 sargs=args 235 sstart=start 236 else: 237 try: 238 r=scommand(blocks) 239 if hasattr(r,'simple_form'): r=r.simple_form 240 result.append(r) 241 except ParseError, m: self.parse_error(m[0],stag,text,l) 242 243 return start
244 245 parse_close__roles__=()
246 - def parse_close(self, text, start, tagre, stag, sloc, scommand, sa):
247 while 1: 248 mo = tagre.search(text,start) 249 if mo is None: self.parse_error('No closing tag', stag, text, sloc) 250 l = mo.start(0) 251 252 try: tag, args, command, coname= self._parseTag(mo,scommand,sa) 253 except ParseError, m: self.parse_error(m[0],m[1], text, l) 254 255 start=l+len(tag) 256 if command: 257 if hasattr(command, 'blockContinuations'): 258 # New open tag. Need to find closing tag. 259 start=self.parse_close(text, start, tagre, tag, l, 260 command,args) 261 elif not coname: return start
262 263 shared_globals__roles__=() 264 shared_globals={} 265
266 - def __init__(self, source_string='', mapping=None, __name__='<string>', 267 **vars):
268 """\ 269 Create a document template from a string. 270 271 The optional parameter, 'mapping', may be used to provide a 272 mapping object containing defaults for values to be inserted. 273 """ 274 self.raw=source_string 275 self.initvars(mapping, vars) 276 self.setName(__name__)
277 278
279 - def name(self): return self.__name__
280 id=name 281 282 setName__roles__=()
283 - def setName(self,v): self.__dict__['__name__']=v
284 285 default__roles__=()
286 - def default(self,name=None,**kw):
287 """\ 288 Change or query default values in a document template. 289 290 If a name is specified, the value of the named default value 291 before the operation is returned. 292 293 Keyword arguments are used to provide default values. 294 """ 295 if name: name=self.globals[name] 296 for key in kw.keys(): self.globals[key]=kw[key] 297 return name
298 299 var__roles__=()
300 - def var(self,name=None,**kw):
301 """\ 302 Change or query a variable in a document template. 303 304 If a name is specified, the value of the named variable before 305 the operation is returned. 306 307 Keyword arguments are used to provide variable values. 308 """ 309 if name: name=self._vars[name] 310 for key in kw.keys(): self._vars[key]=kw[key] 311 return name
312 313 munge__roles__=()
314 - def munge(self,source_string=None,mapping=None,**vars):
315 """\ 316 Change the text or default values for a document template. 317 """ 318 if mapping is not None or vars: 319 self.initvars(mapping, vars) 320 if source_string is not None: 321 self.raw=source_string 322 self.cook()
323 324 manage_edit__roles__=()
325 - def manage_edit(self,data,REQUEST=None):
326 self.munge(data)
327 328 read_raw__roles__=()
329 - def read_raw(self,raw=None):
330 return self.raw
331 332 read__roles__=()
333 - def read(self,raw=None):
334 return self.read_raw()
335 336 cook__roles__=()
337 - def cook(self, 338 cooklock=thread.allocate_lock(), 339 ):
340 cooklock.acquire() 341 try: 342 self._v_blocks=self.parse(self.read()) 343 self._v_cooked=None 344 finally: 345 cooklock.release()
346 347 initvars__roles__=()
348 - def initvars(self, globals, vars):
349 if globals: 350 for k in globals.keys(): 351 if k[:1] != '_' and not vars.has_key(k): vars[k]=globals[k] 352 self.globals=vars 353 self._vars={}
354 355 ZDocumentTemplate_beforeRender__roles__ = ()
356 - def ZDocumentTemplate_beforeRender(self, md, default):
357 return default
358 359 ZDocumentTemplate_afterRender__roles__ = ()
360 - def ZDocumentTemplate_afterRender(self, md, result):
361 pass
362
363 - def __call__(self,client=None,mapping={},**kw):
364 '''\ 365 Generate a document from a document template. 366 367 The document will be generated by inserting values into the 368 format string specified when the document template was 369 created. Values are inserted using standard python named 370 string formats. 371 372 The optional argument 'client' is used to specify a object 373 containing values to be looked up. Values will be looked up 374 using getattr, so inheritence of values is supported. Note 375 that names beginning with '_' will not be looked up from the 376 client. 377 378 The optional argument, 'mapping' is used to specify a mapping 379 object containing values to be inserted. 380 381 Values to be inserted may also be specified using keyword 382 arguments. 383 384 Values will be inserted from one of several sources. The 385 sources, in the order in which they are consulted, are: 386 387 o Keyword arguments, 388 389 o The 'client' argument, 390 391 o The 'mapping' argument, 392 393 o The keyword arguments provided when the object was 394 created, and 395 396 o The 'mapping' argument provided when the template was 397 created. 398 399 ''' 400 # print '============================================================' 401 # print '__called__' 402 # print self.raw 403 # print kw 404 # print client 405 # print mapping 406 # print '============================================================' 407 408 if mapping is None: mapping = {} 409 410 if not hasattr(self,'_v_cooked'): 411 try: changed=self.__changed__() 412 except: changed=1 413 self.cook() 414 if not changed: self.__changed__(0) 415 416 pushed=None 417 try: 418 if mapping.__class__ is TemplateDict: pushed=0 419 except: pass 420 421 globals=self.globals 422 if pushed is not None: 423 # We were passed a TemplateDict, so we must be a sub-template 424 md=mapping 425 push=md._push 426 if globals: 427 push(self.globals) 428 pushed=pushed+1 429 else: 430 md=TemplateDict() 431 push=md._push 432 shared_globals=self.shared_globals 433 if shared_globals: push(shared_globals) 434 if globals: push(globals) 435 if mapping: 436 push(mapping) 437 md.validate=self.validate 438 if client is not None: 439 if type(client)==type(()): 440 md.this=client[-1] 441 else: md.this=client 442 pushed=0 443 444 level=md.level 445 if level > 200: raise SystemError, ( 446 'infinite recursion in document template') 447 md.level=level+1 448 449 if client is not None: 450 if type(client)==type(()): 451 # if client is a tuple, it represents a "path" of clients 452 # which should be pushed onto the md in order. 453 for ob in client: 454 push(InstanceDict(ob, md)) # Circ. Ref. 8-| 455 pushed=pushed+1 456 else: 457 # otherwise its just a normal client object. 458 push(InstanceDict(client, md)) # Circ. Ref. 8-| 459 pushed=pushed+1 460 461 if self._vars: 462 push(self._vars) 463 pushed=pushed+1 464 465 if kw: 466 push(kw) 467 pushed=pushed+1 468 469 try: 470 value = self.ZDocumentTemplate_beforeRender(md, _marker) 471 if value is _marker: 472 try: result = render_blocks(self._v_blocks, md) 473 except DTReturn, v: result = v.v 474 self.ZDocumentTemplate_afterRender(md, result) 475 return result 476 else: 477 return value 478 finally: 479 if pushed: md._pop(pushed) # Get rid of circular reference! 480 md.level=level # Restore previous level
481 482 validate__roles__=() 483 validate=None 484
485 - def __str__(self):
486 return self.read()
487
488 - def __getstate__(self, _special=('_v_', '_p_')):
489 # Waaa, we need _v_ behavior but we may not subclass Persistent 490 d={} 491 for k, v in self.__dict__.items(): 492 if k[:3] in _special: continue 493 d[k]=v 494 return d
495
496 -class FileMixin:
497 # Mix-in class to abstract certain file-related attributes 498 edited_source='' 499
500 - def __init__(self, file_name='', mapping=None, __name__='', **vars):
501 """\ 502 Create a document template based on a named file. 503 504 The optional parameter, 'mapping', may be used to provide a 505 mapping object containing defaults for values to be inserted. 506 """ 507 self.raw=file_name 508 self.initvars(mapping, vars) 509 self.setName(__name__ or file_name)
510 511 read_raw__roles__=()
512 - def read_raw(self):
513 if self.edited_source: return self.edited_source 514 if self.raw: return open(self.raw,'r').read() 515 return ''
516
517 -class File(FileMixin, String):
518 """\ 519 Document templates read from files. 520 521 If the object is pickled, the file name, rather 522 than the file contents is pickled. When the object is 523 unpickled, then the file will be re-read to obtain the string. 524 Note that the file will not be read until the document 525 template is used the first time. 526 """ 527 manage_edit__roles__=()
528 - def manage_edit(self,data): raise TypeError, 'cannot edit files'
529

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.structured_text.StructuredTextProcessor-class.html0000664000076400007640000006357411122067146032600 0ustar stefanstefan qm.structured_text.StructuredTextProcessor
Package qm :: Module structured_text :: Class StructuredTextProcessor
[hide private]
[frames] | no frames]

Class StructuredTextProcessor

source code

Parser and formatter for Python structured text.

Instance Methods [hide private]
 
__init__(self, formatter)
Create a new structured text processor.
source code
 
NormalizeSpaces(self, text)
Return 'text' with spaces normalized.
source code
 
__call__(self, text)
Process structured text 'text'.
source code
 
End(self)
Stop processing text, and do any necessary cleanup.
source code
 
__PushType(self, type, indentation)
Start a new environment.
source code
 
__PopType(self)
End and remove the innermost environment.
source code
 
__SetType(self, type, indentation, label=None)
Set the environment type and indentation level.
source code
 
__WriteText(self, text)
Write paragraph text.
source code
Class Variables [hide private]
  __punctuation = '[][)(.,!?;:\'" ]'
  __bullet_regex = re.compile(r'^[-o\*] +')
  __sequence_regex = re.compile(r'^([A-Za-z]+\.|[0-9]+\.?)+ +')
  __definition_regex = re.compile(r'^(.*) +-- +')
  __collapse_regex = re.compile(r'(?m) *\n *')
  __indent_regex = re.compile(r'^ *')
  __literal_regex = re.compile(r'( +|^)\'([^\']+)\'([\]\[\)\(\.,...
  __strong_regex = re.compile(r'( +|^)\*\*([^\*]+)\*\*([\]\[\)\(...
  __emph_regex = re.compile(r'( +|^)\*([^\*]+)\*([\]\[\)\(\.,!\?...
  __underline_regex = re.compile(r'( +|^)_([^_]+)_([\]\[\)\(\.,!...
  __link_regex = re.compile(r'"([^"]*)"')
  __link_footnote_regex = re.compile(r'\n\.\. *"([^"]*)" *([^ \n...
  __non_nestable_types = ['paragraph']
Method Details [hide private]

__init__(self, formatter)
(Constructor)

source code 

Create a new structured text processor.

'formatter' -- The formatter to use to generate output.


Class Variable Details [hide private]

__literal_regex

Value:
re.compile(r'( +|^)\'([^\']+)\'([\]\[\)\(\.,!\?;:\'" ]+|$)')

__strong_regex

Value:
re.compile(r'( +|^)\*\*([^\*]+)\*\*([\]\[\)\(\.,!\?;:\'" ]+|$)')

__emph_regex

Value:
re.compile(r'( +|^)\*([^\*]+)\*([\]\[\)\(\.,!\?;:\'" ]+|$)')

__underline_regex

Value:
re.compile(r'( +|^)_([^_]+)_([\]\[\)\(\.,!\?;:\'" ]+|$)')

__link_footnote_regex

Value:
re.compile(r'\n\.\. *"([^"]*)" *([^ \n]*)[^\n]*')

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Return.DTReturn-class.html0000664000076400007640000001240311122067146033047 0ustar stefanstefan qm.external.DocumentTemplate.DT_Return.DTReturn
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Return :: Class DTReturn
[hide private]
[frames] | no frames]

Class DTReturn

source code

Instance Methods [hide private]
 
__init__(self, v) source code
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_result_stream-module.html0000664000076400007640000001210011122067145030735 0ustar stefanstefan qm.test.classes.xml_result_stream
Package qm :: Package test :: Package classes :: Module xml_result_stream
[hide private]
[frames] | no frames]

Module xml_result_stream

source code

Classes [hide private]
  XMLResultStream
An 'XMLResultStream' writes out results as XML.
  XMLResultReader
Reads in 'Result's from an XML-formatted results file.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.tet_stream-module.html0000664000076400007640000001125311122067145027343 0ustar stefanstefan qm.test.classes.tet_stream
Package qm :: Package test :: Package classes :: Module tet_stream
[hide private]
[frames] | no frames]

Module tet_stream

source code

Classes [hide private]
  TETStream
A 'TETStream' formats results as a TET journal.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.cmdline-module.html0000664000076400007640000001135511122067145024200 0ustar stefanstefan qm.cmdline
Package qm :: Module cmdline
[hide private]
[frames] | no frames]

Module cmdline

source code

Classes [hide private]
  CommandError
  CommandParser
Class for the functionality that parses the command line.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.serial_target-module.html0000664000076400007640000000214511122067144030603 0ustar stefanstefan serial_target

Module serial_target


Classes

SerialTarget

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_database-pysrc.html0000664000076400007640000050470611122067157027510 0ustar stefanstefan qm.test.classes.xml_database
Package qm :: Package test :: Package classes :: Module xml_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.xml_database

  1  ######################################################################## 
  2  # 
  3  # File:   xml_database.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-03-08 
  6  # 
  7  # Contents: 
  8  #   XML-based test database implementation. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import os 
 21  import qm.common 
 22  from   qm.extension import get_class_arguments 
 23  import qm.fields 
 24  import qm.label 
 25  import qm.structured_text 
 26  import qm.test.base 
 27  from   qm.test.database import * 
 28  from   qm.test.file_database import * 
 29  from   qm.test.suite import * 
 30  from   qm.test.classes.explicit_suite import ExplicitSuite 
 31  import qm.xmlutil 
 32  import shutil 
 33  import string 
 34  import xml 
 35  import xml.dom 
 36  import xml.sax 
 37   
 38  ######################################################################## 
 39  # classes 
 40  ######################################################################## 
 41   
42 -class TestFileError(RuntimeError):
43 """An error in the format or contents of an XML test file.""" 44 45 pass
46 47 48
49 -class XMLDatabase(ExtensionDatabase):
50 """A database representing tests as XML files in a directory tree.""" 51
52 - def __init__(self, path, arguments):
53 54 # Initialize base classes. 55 ExtensionDatabase.__init__(self, path, arguments) 56 # Create an AttachmentStore for this database. 57 self.__store = qm.attachment.FileAttachmentStore(path)
58 59
60 - def _GetTestFromPath(self, test_id, test_path):
61 try: 62 return self.__LoadItem(test_id, test_path, 63 self.__ParseTestDocument) 64 except Exception, exception: 65 # Problem while parsing XML. 66 message = qm.error("error loading xml test", 67 test_id=test_id, 68 message=str(exception)) 69 raise TestFileError, message
70 71
72 - def _GetResourceFromPath(self, resource_id, resource_path):
73 try: 74 return self.__LoadItem(resource_id, resource_path, 75 self.__ParseResourceDocument) 76 except Exception, exception: 77 # Problem while parsing XML. 78 message = qm.error("error loading xml resource", 79 resource_id=resource_id, 80 message=str(exception)) 81 raise TestFileError, message
82 83 # Helper functions. 84
85 - def __StoreAttachments(self, item):
86 """Store all attachments in 'item' in the attachment store. 87 88 'item' -- A 'Test' or 'Resource'. If any of its fields contain 89 attachments, add them to the 'AttachmentStore'.""" 90 91 # Get all of the attachments associated with the new item. 92 new_attachments = item.GetAttachments() 93 94 # Remove old attachments that are not also among the new 95 # attachments. 96 store = self.GetAttachmentStore() 97 try: 98 old_item = self.GetItem(item.kind, item.GetId()) 99 except: 100 old_item = None 101 if old_item: 102 old_attachments = old_item.GetItem().GetAttachments() 103 for o in old_attachments: 104 found = 0 105 for n in new_attachments: 106 if (n.GetStore() == store 107 and n.GetFileName() == o.GetFileName()): 108 found = 1 109 break 110 if not found: 111 store.Remove(o.GetLocation()) 112 113 # Put any new attachments into the attachment store. 114 for a in new_attachments: 115 if a.GetStore() != store: 116 location = self.__MakeDataFilePath(item.GetId(), 117 a.GetFileName()) 118 a.Move(store, location)
119 120
121 - def __MakeDataFilePath(self, item_id, file_name):
122 """Construct the path to an attachment data file. 123 124 'item_id' -- The test or resource item of which the attachment 125 is part. 126 127 'file_name' -- The file name specified for the attachment.""" 128 129 # Convert the item's containing suite to a path. 130 parent_suite_path \ 131 = os.path.dirname(self._GetPathFromLabel(item_id)) 132 # The relative part of the eventual full file name will be 133 # the part after the parent_suite_path and the directory 134 # name separator character(s). 135 abs_len = len(parent_suite_path) + len(os.sep) 136 137 # Construct a file name free of suspicious characters. 138 base, extension = os.path.splitext(file_name) 139 safe_file_name = qm.label.thunk(base) + extension 140 141 data_file_path = os.path.join(parent_suite_path, safe_file_name) 142 # Is the file name by itself OK in this directory? It must not 143 # have a file extension used by the XML database itself, and 144 # there must be no other file with the same name there. 145 if extension not in [self.GetTestExtension(), 146 self.GetSuiteExtension(), 147 self.GetResourceExtension()] \ 148 and not os.path.exists(data_file_path): 149 return data_file_path[abs_len:] 150 151 # No good. Construct alternate names by appending numbers 152 # incrementally. 153 index = 0 154 while 1: 155 data_file_path = os.path.join(parent_suite_path, 156 safe_file_name + ".%d" % index) 157 if not os.path.exists(data_file_path): 158 return data_file_path[abs_len:] 159 index = index + 1
160 161
162 - def __LoadItem(self, item_id, path, document_parser):
163 """Load an item (a test or resource) from an XML file. 164 165 This function is used for logic common to tests and resources. 166 167 'item_id' -- The ID of the item to get. 168 169 'path' -- The path to the test or resource file. 170 171 'document_parser' -- A function that takes an XML DOM document 172 as its argument and returns the constructed item object.""" 173 174 # Load and parse the XML item representation. 175 document = qm.xmlutil.load_xml_file(path) 176 # Turn it into an object. 177 item = document_parser(item_id, document) 178 179 return item
180 181
182 - def __ParseTestDocument(self, test_id, document):
183 """Return a test object constructed from a test document. 184 185 'test_id' -- The test ID of the test. 186 187 'document' -- A DOM document containing a single test element 188 from which the test is constructed.""" 189 190 # Parse the DOM node. 191 test_class, arguments \ 192 = (qm.extension.parse_dom_element 193 (document.documentElement, 194 lambda n : qm.test.base.get_test_class(n, self), 195 self.__store)) 196 test_class_name = qm.extension.get_extension_class_name(test_class) 197 # For backwards compatibility, look for "prerequisite" elements. 198 for p in document.documentElement.getElementsByTagName("prerequisite"): 199 if not arguments.has_key("prerequisites"): 200 arguments["prerequisites"] = [] 201 arguments["prerequisites"].append((qm.xmlutil.get_dom_text(p), 202 p.getAttribute("outcome"))) 203 # For backwards compatibility, look for "resource" elements. 204 for r in document.documentElement.getElementsByTagName("resource"): 205 if not arguments.has_key("resources"): 206 arguments["resources"] = [] 207 arguments["resources"].append(qm.xmlutil.get_dom_text(r)) 208 # Construct a descriptor for it. 209 test = TestDescriptor(self, 210 test_id, 211 test_class_name, 212 arguments) 213 return test
214 215
216 - def __ParseResourceDocument(self, resource_id, document):
217 """Return a resource object constructed from a resource document. 218 219 'resource_id' -- The resource ID of the resource. 220 221 'document' -- A DOM document node containing a single resource 222 element from which the resource object is constructed.""" 223 224 # Parse the DOM node. 225 resource_class, arguments \ 226 = (qm.extension.parse_dom_element 227 (document.documentElement, 228 lambda n : qm.test.base.get_resource_class(n, self))) 229 resource_class_name \ 230 = qm.extension.get_extension_class_name(resource_class) 231 # Construct a descriptor for it. 232 resource = ResourceDescriptor(self, 233 resource_id, 234 resource_class_name, 235 arguments) 236 return resource
237 238
239 - def _GetSuiteFromPath(self, suite_id, path):
240 """Load the test suite file at 'path' with suite ID 'suite_id'. 241 242 returns -- A 'Suite' object.""" 243 244 # Make sure there is a file by that name. 245 if not os.path.isfile(path): 246 raise NoSuchSuiteError, "no suite file %s" % path 247 # Load and parse the suite file. 248 document = qm.xmlutil.load_xml_file(path) 249 # For backwards compatibility, handle XML files using the 250 # "suite" tag. New databases will have Suite files using the 251 # "extension" tag. 252 suite = document.documentElement 253 if suite.tagName == "suite": 254 assert suite.tagName == "suite" 255 # Extract the test and suite IDs. 256 test_ids = qm.xmlutil.get_child_texts(suite, "test_id") 257 suite_ids = qm.xmlutil.get_child_texts(suite, "suite_id") 258 # Make sure they're all valid. 259 for id_ in test_ids + suite_ids: 260 if not self.IsValidLabel(id_, is_component = 0): 261 raise RuntimeError, qm.error("invalid id", id=id_) 262 # Construct the suite. 263 return ExplicitSuite({ "is_implicit" : "false", 264 "test_ids" : test_ids, 265 "suite_ids" : suite_ids }, 266 **{ ExplicitSuite.EXTRA_ID : suite_id, 267 ExplicitSuite.EXTRA_DATABASE : self }) 268 else: 269 # Load the extension. 270 extension_class, arguments = \ 271 qm.extension.parse_dom_element( 272 suite, 273 lambda n: get_extension_class(n, "suite", self), 274 self.GetAttachmentStore()) 275 # Construct the actual instance. 276 extras = { extension_class.EXTRA_ID : suite_id, 277 extension_class.EXTRA_DATABASE : self } 278 return extension_class(arguments, **extras)
279 280
281 - def WriteExtension(self, id, extension):
282 283 kind = extension.kind 284 if kind in ("resource", "test"): 285 self.__StoreAttachments(extension) 286 # Figure out what path should be used to store the test. 287 path = self._GetPath(kind, id) 288 # If the file is in a new subdirectory, create it. 289 containing_directory = os.path.dirname(path) 290 if not os.path.isdir(containing_directory): 291 os.makedirs(containing_directory) 292 extension.Write(open(path, "w"))
293 294
295 - def GetAttachmentStore(self):
296 """Returns the 'AttachmentStore' associated with the database. 297 298 returns -- The 'AttachmentStore' containing the attachments 299 associated with tests and resources in this database.""" 300 301 return self.__store
302 303
304 - def _Trace(self, message,):
305 """Write a trace 'message'. 306 307 'message' -- A string to be output as a trace message.""" 308 309 tracer = qm.test.cmdline.get_qmtest().GetTracer() 310 tracer.Write(message, "xmldb")
311 312 313 ######################################################################## 314 # Local Variables: 315 # mode: python 316 # indent-tabs-mode: nil 317 # fill-column: 72 318 # End: 319

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result_reader-module.html0000664000076400007640000001114211122067145026375 0ustar stefanstefan qm.test.result_reader
Package qm :: Package test :: Module result_reader
[hide private]
[frames] | no frames]

Module result_reader

source code

Classes [hide private]
  ResultReader
A 'ResultReader' provides access to stored test results.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Return-pysrc.html0000664000076400007640000007351711122067155031411 0ustar stefanstefan qm.external.DocumentTemplate.DT_Return
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Return
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_Return

 1  ############################################################################## 
 2  # 
 3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
 4  # 
 5  # This software is subject to the provisions of the Zope Public License, 
 6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
 7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
 8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
10  # FOR A PARTICULAR PURPOSE 
11  # 
12  ############################################################################## 
13  __version__='$Revision: 1069 $'[11:-2] 
14   
15  from DT_Util import parse_params, name_param, html_quote, str 
16  import string, sys 
17  from string import find, split, join, atoi, rfind 
18   
19 -class ReturnTag:
20 name='return' 21 expr=None 22
23 - def __init__(self, args):
24 args = parse_params(args, name='', expr='') 25 name, expr = name_param(args,'var',1) 26 self.__name__, self.expr = name, expr
27
28 - def render(self, md):
29 name=self.__name__ 30 val=self.expr 31 if val is None: 32 val = md[name] 33 else: 34 val=val.eval(md) 35 36 raise DTReturn(val)
37 38 __call__ = render 39
40 -class DTReturn:
41 - def __init__(self, v):
42 self.v = v
43

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.fields-module.html0000664000076400007640000000426111122067144024613 0ustar stefanstefan fields

Module fields


Classes

AttachmentField
BooleanField
ChoiceField
DictionaryField
EnumerationField
Field
IntegerField
PythonField
SetField
TextField
TimeField
TupleField
UploadAttachmentPage

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.executable.Filter-class.html0000664000076400007640000003162411122067146025754 0ustar stefanstefan qm.executable.Filter
Package qm :: Module executable :: Class Filter
[hide private]
[frames] | no frames]

Class Filter

source code

   object --+            
            |            
   Executable --+        
                |        
TimeoutExecutable --+    
                    |    
 RedirectedExecutable --+
                        |
                       Filter

A 'FilterExecutable' feeds an input string to another proces.

The input string is provided to a child process via a pipe; the standard output and standard error streams from the child process are collected in the 'Filter'.

Instance Methods [hide private]
 
__init__(self, input, timeout=-1)
Create a new 'Filter'.
source code
 
_WriteStdin(self)
Write to the standard input pipe.
source code

Inherited from TimeoutExecutable: Run

Inherited from Executable: Kill, Spawn

Inherited from Executable (private): _GetChildPID

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, input, timeout=-1)
(Constructor)

source code 

Create a new 'Filter'.

'input' -- The string containing the input to provide to the child process.

'timeout' -- As for 'TimeoutExecutable.__init__'.

Overrides: object.__init__

_WriteStdin(self)

source code 

Write to the standard input pipe.

This implementation writes no data and closes the pipe.

Overrides: RedirectedExecutable._WriteStdin
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.NewSuitePage-class.html0000664000076400007640000003350311122067151027247 0ustar stefanstefan qm.test.web.web.NewSuitePage
Package qm :: Package test :: Package web :: Module web :: Class NewSuitePage
[hide private]
[frames] | no frames]

Class NewSuitePage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      NewSuitePage

Page for creating a new test suite.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, suite_id="", field_errors={})
Create a new DTML context.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, suite_id="", field_errors={})
(Constructor)

source code 

Create a new DTML context.

'server' -- The 'QMTestServer' creating this page.

'suite_id' -- Initial value for the new test suite ID field.

'field_errors' -- A mapping of error messages to fields. If empty, there are no errors.

Overrides: web.DtmlPage.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.explicit_suite.ExplicitSuite-class.html0000664000076400007640000005652111122067147032651 0ustar stefanstefan qm.test.classes.explicit_suite.ExplicitSuite
Package qm :: Package test :: Package classes :: Module explicit_suite :: Class ExplicitSuite
[hide private]
[frames] | no frames]

Class ExplicitSuite

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
            suite.Suite --+
                          |
                         ExplicitSuite

An 'ExplicitSuite' stores all of the test and suite ids explicitly.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
IsImplicit(self)
Return true if this is an implicit test suite.
source code
 
GetTestIds(self)
Return the tests contained in this suite.
source code
 
GetSuiteIds(self)
Return the suites contained in this suite.
source code

Inherited from suite.Suite: GetAllTestAndSuiteIds, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.fields.SetField'> test_ids>, <<class ...
A list of the arguments to the extension class.
  _argument_dictionary = {'is_implicit': <<class 'qm.fields.Bool...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.BooleanField'> is_implici...
A list of all the 'Field's in this class.
  is_implicit = 'false'
  suite_ids = []
  test_ids = []

Inherited from suite.Suite: EXTRA_DATABASE, EXTRA_ID, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

IsImplicit(self)

source code 

Return true if this is an implicit test suite.

Implicit test suites cannot be edited.

Overrides: suite.Suite.IsImplicit
(inherited documentation)

GetTestIds(self)

source code 

Return the tests contained in this suite.

returns -- A sequence of labels corresponding to the tests contained in this suite. Tests that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetTestIds
(inherited documentation)

GetSuiteIds(self)

source code 

Return the suites contained in this suite.

returns -- A sequence of labels corresponding to the suites contained in this suite. Suites that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

Overrides: suite.Suite.GetSuiteIds
(inherited documentation)

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[<<class 'qm.fields.SetField'> test_ids>,
 <<class 'qm.fields.SetField'> suite_ids>,
 <<class 'qm.fields.BooleanField'> is_implicit>]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'is_implicit': <<class 'qm.fields.BooleanField'> is_implicit>,
 'suite_ids': <<class 'qm.fields.SetField'> suite_ids>,
 'test_ids': <<class 'qm.fields.SetField'> test_ids>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.BooleanField'> is_implicit>,
 <<class 'qm.fields.SetField'> suite_ids>,
 <<class 'qm.fields.SetField'> test_ids>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command.build_extensions-module.html0000664000076400007640000001130411122067145030514 0ustar stefanstefan qm.dist.command.build_extensions
Package qm :: Package dist :: Package command :: Module build_extensions
[hide private]
[frames] | no frames]

Module build_extensions

source code

Classes [hide private]
  build_extensions
build extension files.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_If-module.html0000664000076400007640000000303711122067144031364 0ustar stefanstefan DT_If

Module DT_If


Classes

Else
If
Unless

Variables

__doc__
__rcs_id__

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_InSV-module.html0000664000076400007640000000313011122067144031637 0ustar stefanstefan DT_InSV

Module DT_InSV


Classes

sequence_variables

Functions

opt
sub

Variables

__doc__
mv

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.temporary_directory-module.html0000664000076400007640000000216611122067144027455 0ustar stefanstefan temporary_directory

Module temporary_directory


Classes

TemporaryDirectory

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.python-module.html0000664000076400007640000000307211122067144027277 0ustar stefanstefan python

Module python


Classes

BaseExceptionTest
ExceptionTest
ExecTest
StringExceptionTest

Functions

make_namespaces

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.ssh_host-pysrc.html0000664000076400007640000027611111122067156026711 0ustar stefanstefan qm.test.classes.ssh_host
Package qm :: Package test :: Package classes :: Module ssh_host
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.ssh_host

  1  ######################################################################## 
  2  # 
  3  # File:   ssh_host.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2005-06-03 
  6  # 
  7  # Contents: 
  8  #   SSHHost, RSHHost 
  9  # 
 10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ####################################################################### 
 17   
 18  from   qm.host import Host 
 19  import os 
 20  import os.path 
 21  from   qm.fields import TextField, SetField 
 22  import qm.common 
 23  import sys 
 24   
 25  ######################################################################## 
 26  # Classes 
 27  ####################################################################### 
 28   
29 -class SSHHost(Host):
30 """An 'SSHHost' is accessible via 'ssh' or a similar program.""" 31 32 # If not empty, the name of the remote host. 33 host_name = TextField() 34 # The path to "ssh". 35 ssh_program = TextField( 36 default_value = "ssh", 37 description = """The path to the remote shell program.""" 38 ) 39 # Any arguments that must be provided to "ssh". 40 ssh_args = SetField( 41 TextField(description = 42 """The arguments to the remote shell program.""")) 43 # The path to "scp". 44 scp_program = TextField( 45 default_value = "scp", 46 description = """The path to the remote copy program.""" 47 ) 48 # Any arguments that must be provided to "scp". 49 scp_args = SetField( 50 TextField(description = 51 """The arguments to the remote copy program.""")) 52 # The default directory on the remote system. 53 default_dir = TextField( 54 description = """The default directory on the remote system.""" 55 ) 56 57 nfs_dir = TextField( 58 description = """The default directory, as seen from the local host. 59 60 If not empty, 'nfs_dir' is a directory on the local machine 61 that is equivalent to the default directory on the remote 62 machine. In that case, files will be copied to and from this 63 directory on the local machine, rather than by using 64 'scp'.""" 65 ) 66 67 user_name = TextField( 68 description = """The user name on the remote host. 69 70 If not empty, the user name that should be used when 71 connecting to the remote host.""" 72 ) 73
74 - def Run(self, path, arguments, environment = None, timeout = -1, 75 relative = False):
76 77 default_dir = self.default_dir 78 if not default_dir: 79 default_dir = os.curdir 80 if (relative 81 or (not os.path.isabs(path) 82 and (path.find(os.path.sep) != -1 83 or (os.path.altsep 84 and path.find(os.path.altsep) != -1)))): 85 path = os.path.join(default_dir, path) 86 path, arguments = self._FormSSHCommandLine(path, arguments, 87 environment) 88 return super(SSHHost, self).Run(path, arguments, None, timeout)
89 90
91 - def UploadFile(self, local_file, remote_file = None):
92 93 if remote_file is None: 94 remote_file = os.path.basename(local_file) 95 if self.nfs_dir: 96 remote_file = os.path.join(self.nfs_dir, remote_file) 97 super(SSHHost, self).UploadFile(local_file, remote_file) 98 else: 99 if self.default_dir: 100 remote_file = os.path.join(self.default_dir, remote_file) 101 command = self._FormSCPCommandLine(True, local_file, 102 remote_file) 103 executable = self.Executable() 104 status = executable.Run(command) 105 if ((sys.platform != "win32" 106 and (not os.WIFEXITED(status) 107 or os.WEXITSTATUS(status) != 0)) 108 or (sys.platform == "win32" and status != 0)): 109 raise qm.common.QMException("could not upload file")
110 111
112 - def DownloadFile(self, remote_file, local_file = None):
113 114 if local_file is None: 115 local_file = os.path.basename(remote_file) 116 if self.nfs_dir: 117 remote_file = os.path.join(self.nfs_dir, remote_file) 118 super(SSHHost, self).DownloadFile(remote_file, local_file) 119 else: 120 if self.default_dir: 121 remote_file = os.path.join(self.default_dir, remote_file) 122 command = self._FormSCPCommandLine(False, local_file, 123 remote_file) 124 executable = self.Executable() 125 executable.Run(command)
126 127
128 - def DeleteFile(self, remote_file):
129 130 if self.default_dir: 131 remote_file = os.path.join(self.default_dir, remote_file) 132 return self.Run("rm", [remote_file])
133 134
135 - def _FormSSHCommandLine(self, path, arguments, environment = None):
136 """Form the 'ssh' command line. 137 138 'path' -- The remote command, in the same format expected by 139 'Run'. 140 141 'arguments' -- The arguments to the remote command. 142 143 'environment' -- As for 'Run'. 144 145 returns -- A pair '(path, arguments)' describing the command 146 to run on the local machine that will execute the remote 147 command.""" 148 149 command = self.ssh_args + [self.host_name] 150 if self.user_name: 151 command += ["-l", self.user_name] 152 if environment is not None: 153 command.append("env") 154 for (k, v) in environment.iteritems(): 155 command.append("%s=%s" % (k, v)) 156 command.append(path) 157 command += arguments 158 159 return self.ssh_program, command
160 161
162 - def _FormSCPCommandLine(self, upload, local_file, remote_file):
163 """Form the 'scp' command line. 164 165 'upload' -- True iff the 'local_file' should be copied to the 166 remote host. 167 168 'local_file' -- The path to the local file. 169 170 'remote_file' -- The path to the remote file. 171 172 returns -- The list of arguments for a command to run on the 173 local machine that will perform the file copy.""" 174 175 if self.default_dir: 176 remote_file = os.path.join(self.default_dir, remote_file) 177 remote_file = self.host_name + ":" + remote_file 178 if self.user_name: 179 remote_file = self.user_name + "@" + remote_file 180 command = [self.scp_program] + self.scp_args 181 if upload: 182 command += [local_file, remote_file] 183 else: 184 command += [remote_file, local_file] 185 186 return command
187 188 189
190 -class RSHHost(SSHHost):
191 """An 'RSHHost' is an 'SSHHost' that uses 'rsh' instead of 'ssh'. 192 193 The reason that 'RSHHost' is a separate class is that (a) that 194 makes it easier for users to construct an 'SSHHost', and (b) 'rsh' 195 does not return the exit code of the remote program, so 'Run' 196 requires adjustment.""" 197 198 # Override the default values. 199 ssh_program = TextField( 200 default_value = "rsh", 201 description = """The path to the remote shell program.""" 202 ) 203 scp_program = TextField( 204 default_value = "rcp", 205 description = """The path to the remote copy program.""" 206 ) 207
208 - def Run(self, path, arguments, environment = None, timeout = -1):
209 210 status, output = \ 211 super(RSHHost, self).Run(path, arguments, 212 environment, timeout) 213 # The exit status of 'rsh' is not the exit status of the 214 # remote program. The exit status of the remote program is 215 # unavailable. 216 return (None, output)
217

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.file_label.FileLabel-class.html0000664000076400007640000003364311122067147030721 0ustar stefanstefan qm.test.classes.file_label.FileLabel
Package qm :: Package test :: Package classes :: Module file_label :: Class FileLabel
[hide private]
[frames] | no frames]

Class FileLabel

source code

label.Label --+
              |
             FileLabel

A 'FileLabel' is a 'Label' that uses the filesystem's naming scheme.

A 'FileLabel' is a 'Label' whose separator character is the operating system's file system separator character (typically '/' or '\'). These labels are not system-independent; there is no guarantee that 'FileLabel's will have the same meaning on different operating systems.

Instance Methods [hide private]
 
Join(self, *labels)
Combine this label and the 'labels' into a single label.
source code
 
Split(self)
Split the label into a pair '(directory, basename)'.
source code
 
Basename(self)
Return the basename for the label.
source code
 
Dirname(self)
Return the directory name for the 'label'.
source code

Inherited from label.Label: IsValid, SplitLeft, __init__, __str__

Class Variables [hide private]
  _sep = '/'
Method Details [hide private]

Join(self, *labels)

source code 

Combine this label and the 'labels' into a single label.

'labels' -- A sequence of strings giving the components of the new label. All but the last are taken as directory names; the last is treated as a basename.

Overrides: label.Label.Join

Split(self)

source code 

Split the label into a pair '(directory, basename)'.

returns -- A pair '(directory, basename)', each of which is a label.

It is always true that 'directory.join(basename)' will return a label equivalent to the original label.

Overrides: label.Label.Split

Basename(self)

source code 

Return the basename for the label.

returns -- A string giving the basename for the label. The value returned for 'l.basename()' is always the same as 'l.split()[1]'.

Overrides: label.Label.Basename

Dirname(self)

source code 

Return the directory name for the 'label'.

returns -- A string giving the directory name for the 'label'. The value returned for 'l.dirname()' is always the same as 'l.split()[0]'.

Overrides: label.Label.Dirname

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-E.html0000664000076400007640000006242111122067144024276 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

E



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.Item-class.html0000664000076400007640000001555411122067151025613 0ustar stefanstefan qm.test.web.web.Item
Package qm :: Package test :: Package web :: Module web :: Class Item
[hide private]
[frames] | no frames]

Class Item

source code

An 'Item' provides a convenient way to pass around named values. It is iterated over in listings generated by various dtml templates.

Instance Methods [hide private]
 
__init__(self, id, **kwds)
Construct a new 'Item'.
source code
Method Details [hide private]

__init__(self, id, **kwds)
(Constructor)

source code 

Construct a new 'Item'.

'id' -- The identifier.

'kwds' -- A dictionary of named values to store.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.simulator-module.html0000664000076400007640000000212311122067144027771 0ustar stefanstefan simulator

Module simulator


Classes

Simulator

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test.Test.OutcomeField-class.html0000664000076400007640000003013011122067151027623 0ustar stefanstefan qm.test.test.Test.OutcomeField
Package qm :: Package test :: Module test :: Class Test :: Class OutcomeField
[hide private]
[frames] | no frames]

Class OutcomeField

  object --+                
           |                
fields.Field --+            
               |            
fields.TextField --+        
                   |        
  fields.ChoiceField --+    
                       |    
 fields.EnumerationField --+
                           |
                          Test.OutcomeField

An 'OutcomeField' contains an outcome.

Instance Methods [hide private]
 
__init__(self, name, **properties)
Create an enumeration field.

Inherited from fields.EnumerationField: GetHelp, GetItems, GetValueFromDomNode, MakeDomNodeForValue

Inherited from fields.ChoiceField: FormatValueAsHtml, Validate

Inherited from fields.TextField: FormatValueAsText, ParseFormValue, ParseTextValue

Inherited from fields.Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from fields.Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name, **properties)
(Constructor)

 

Create an enumeration field.

'enumerals' -- A sequence of strings of available enumerals.

'default_value' -- The default value for this enumeration. If 'None', the first enumeral is used.

Overrides: object.__init__
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.local_host-module.html0000664000076400007640000000212611122067144030104 0ustar stefanstefan local_host

Module local_host


Classes

LocalHost

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_UI-module.html0000664000076400007640000001523611122067145030565 0ustar stefanstefan qm.external.DocumentTemplate.DT_UI
Package qm :: Package external :: Package DocumentTemplate :: Module DT_UI
[hide private]
[frames] | no frames]

Module DT_UI

source code

Machinery to support through-the-web editing

$Id: DT_UI.py 1069 2008-11-13 21:55:43Z stefan $


Version: 1069

Variables [hide private]
  __doc__ = '''Machinery to support through-the-web edit...
  FactoryDefaultString = 'Factory Default'
Variables Details [hide private]

__doc__

Value:
'''Machinery to support through-the-web editing

$Id: DT_UI.py 1069 2008-11-13 21:55:43Z stefan $'''

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.process_target.ProcessTarget-class.html0000664000076400007640000006411011122067147032626 0ustar stefanstefan qm.test.classes.process_target.ProcessTarget
Package qm :: Package test :: Package classes :: Module process_target :: Class ProcessTarget
[hide private]
[frames] | no frames]

Class ProcessTarget

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
          target.Target --+
                          |
                         ProcessTarget

A 'ProcessTarget' runs tests in child processes.

Nested Classes [hide private]
  QMTestExecutable
A 'QMTestExecutable' redirects commands to a child process.

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, properties)
Construct a new 'ProcessTarget'.
source code
 
IsIdle(self)
Return true if the target is idle.
source code
 
Start(self, response_queue, engine=None)
Start the target.
source code
 
Stop(self)
Stop the target.
source code
 
RunTest(self, descriptor, context)
Run the test given by 'test_id'.
source code
 
_GetInterpreter(self)
Return the interpreter to use.
source code
 
__ReadResults(self, fd)
Read results from one of the children.
source code

Inherited from target.Target: GetDatabase, GetGroup, GetName, IsInGroup

Inherited from target.Target (private): _BeginResourceSetUp, _CleanUpResource, _FinishResourceSetUp, _GetTemporaryDirectory, _RecordResult, _SetUpResource

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.IntegerField(name= "processes", title= ...
A list of the arguments to the extension class.

Inherited from target.Target: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, properties)
(Constructor)

source code 

Construct a new 'ProcessTarget'.

'database' -- The 'Database' containing the tests that will be run.

'properties' -- A dictionary mapping strings (property names) to strings (property values).

Overrides: object.__init__

IsIdle(self)

source code 

Return true if the target is idle.

returns -- True if the target is idle. If the target is idle, additional tasks may be assigned to it.

Overrides: target.Target.IsIdle

Start(self, response_queue, engine=None)

source code 

Start the target.

'response_queue' -- The 'Queue' in which the results of test executions are placed.

'engine' -- The 'ExecutionEngine' that is starting the target, or 'None' if this target is being started without an 'ExecutionEngine'.

Overrides: target.Target.Start

Stop(self)

source code 

Stop the target.

postconditions -- The target may no longer be used.

Overrides: target.Target.Stop

RunTest(self, descriptor, context)

source code 

Run the test given by 'test_id'.

'descriptor' -- The 'TestDescriptor' for the test.

'context' -- The 'Context' in which to run the test.

Overrides: target.Target.RunTest

_GetInterpreter(self)

source code 

Return the interpreter to use.

returns -- A list giving the path to an interpreter, and arguments to provide the interpreter. This interpreter is used to run QMTest. If '[]' is returned, then no intepreter is used.

__ReadResults(self, fd)

source code 

Read results from one of the children.

'fd' -- The descriptor from which the results should be read.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.IntegerField(name= "processes", title= "Number of Processes\
", description= """The number of processes to devote to running tests.

            A positive integer that indicates the number of processes \
to
            use when running tests.  Larger numbers will allow more
            tests to be run at once.  You can experiment with this
            value to find the number that results in the fastest
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.DictionaryField-class.html0000664000076400007640000006524611122067146026734 0ustar stefanstefan qm.fields.DictionaryField
qm :: fields :: DictionaryField :: Class DictionaryField
[hide private]
[frames] | no frames]

Class DictionaryField

source code

object --+    
         |    
     Field --+
             |
            DictionaryField

A 'DictionaryField' maps keys to values.

Instance Methods [hide private]
 
__init__(self, key_field, value_field, **properties)
Construct a new 'DictionaryField'.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
GetKeyField(self) source code
 
GetValueField(self) source code
 
FormatValueAsHtml(self, server, content, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
MakeDomNodeForValue(self, value, document)
Generate a DOM element node for a value of this field.
source code
 
Validate(self, value)
Validate a field value.
source code
 
ParseTextValue(self, value)
Parse a value represented as a string.
source code
 
ParseFormValue(self, request, name, attachment_stores)
Convert a value submitted from an HTML form.
source code
 
GetValueFromDomNode(self, node, attachment_store)
Return a value for this field represented by DOM 'node'.
source code

Inherited from Field: FormatValueAsText, GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, key_field, value_field, **properties)
(Constructor)

source code 

Construct a new 'DictionaryField'.

'key_field' -- The key field.

'value_field' -- The value field.

Overrides: object.__init__

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: Field.GetHelp
(inherited documentation)

FormatValueAsHtml(self, server, content, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

Overrides: Field.FormatValueAsHtml
(inherited documentation)

MakeDomNodeForValue(self, value, document)

source code 

Generate a DOM element node for a value of this field.

'value' -- The value to represent.

'document' -- The containing DOM document node.

Overrides: Field.MakeDomNodeForValue
(inherited documentation)

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

Overrides: Field.Validate
(inherited documentation)

ParseTextValue(self, value)

source code 

Parse a value represented as a string.

'value' -- A string representing the value.

returns -- The corresponding field value. The value returned should be processed by 'Validate' to ensure that it is valid before it is returned.

Overrides: Field.ParseTextValue
(inherited documentation)

ParseFormValue(self, request, name, attachment_stores)

source code 

Convert a value submitted from an HTML form.

'request' -- The 'WebRequest' containing a value corresponding to this field.

'name' -- The name corresponding to this field in the 'request'.

'attachment_stores' -- A dictionary mapping 'AttachmentStore' ids (in the sense of Python's 'id' built-in) to the 'AttachmentStore's themselves.

returns -- A pair '(value, redisplay)'. 'value' is the value for this field, as indicated in 'request'. 'redisplay' is true if and only if the form should be redisplayed, rather than committed. If an error occurs, an exception is thrown.

Overrides: Field.ParseFormValue
(inherited documentation)

GetValueFromDomNode(self, node, attachment_store)

source code 

Return a value for this field represented by DOM 'node'.

This method does not validate the value for this particular instance; it only makes sure the node is well-formed, and returns a value of the correct Python type.

'node' -- The DOM node that is being evaluated.

'attachment_store' -- For attachments, the store that should be used.

If the 'node' is incorrectly formed, this method should raise an exception.

Overrides: Field.GetValueFromDomNode
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.CGIWebRequest-class.html0000664000076400007640000002473111122067151025571 0ustar stefanstefan qm.web.CGIWebRequest
Package qm :: Module web :: Class CGIWebRequest
[hide private]
[frames] | no frames]

Class CGIWebRequest

source code

A 'WebRequest' object initialized from the CGI environment.

Instance Methods [hide private]
 
__init__(self)
Create a new request from the current CGI environment.
source code
 
GetUrl(self) source code
 
__getitem__(self, key) source code
 
keys(self) source code
 
has_key(self, key) source code
 
copy(self)
Return a copy of the request.
source code
Method Details [hide private]

__init__(self)
(Constructor)

source code 

Create a new request from the current CGI environment.

preconditions -- The CGI environment (environment variables etc.) must be in place.

copy(self)

source code 

Return a copy of the request.

The copy isn't tied to the CGI environment, so it can be modified safely.


qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-N.html0000664000076400007640000003572011122067144024311 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

N



qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-D.html0000664000076400007640000006417711122067144024307 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

D



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_database-pysrc.html0000664000076400007640000061702511122067160026164 0ustar stefanstefan qm.test.file_database
Package qm :: Package test :: Module file_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.file_database

  1  ######################################################################## 
  2  # 
  3  # File:   file_database.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2001-10-05 
  6  # 
  7  # Contents: 
  8  #   FileDatabase 
  9  #   ExtensionDatabase 
 10  # 
 11  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 12  # 
 13  # For license terms see the file COPYING. 
 14  # 
 15  ######################################################################## 
 16   
 17  ######################################################################## 
 18  # Imports 
 19  ######################################################################## 
 20   
 21  import dircache 
 22  import os 
 23  import os.path 
 24  from   qm.test.database import * 
 25  from   qm.test.directory_suite import * 
 26   
 27  ######################################################################## 
 28  # Classes 
 29  ######################################################################## 
 30   
31 -class FileDatabase(Database):
32 """A 'FileDatabase' stores each test as a single file. 33 34 A 'FileDatabase' is a 'Database' that stores each test, suite, 35 or resource as a single file. In addition, some subdirectories 36 can be considered implicit suites. The contents of the 37 implicit suite are all of the tests and suites contained in the 38 subdirectory. 39 40 'FileDatabase' is an abstract class.""" 41 42 # Methods that deal with tests. 43
44 - def GetTest(self, test_id):
45 """Return the 'TestDescriptor' for the test named 'test_id'. 46 47 'test_id' -- A label naming the test. 48 49 returns -- A 'TestDescriptor' corresponding to 'test_id'. 50 51 raises -- 'NoSuchTestError' if there is no test in the database 52 named 'test_id'.""" 53 54 path = self.GetTestPath(test_id) 55 if not self._IsTestFile(path): 56 raise NoSuchTestError, test_id 57 58 return self._GetTestFromPath(test_id, os.path.normpath(path))
59 60
61 - def GetTestPath(self, test_id):
62 """Return the file containing 'test_id'. 63 64 'test_id' -- The name of a test. 65 66 returns -- The absolute file name of the file that contains, or 67 would contain, 'test_id'. This method works even if no test 68 named 'test_id' exists. 69 70 Derived classes may override this method.""" 71 72 return self._GetPathFromLabel(test_id)
73 74
75 - def _IsTestFile(self, path):
76 """Returns true if 'path' is a test file. 77 78 'path' -- The absolute name of a file. All relevant 79 components in the path name have already been checked to 80 ensure that they are valid labels. 81 82 returns -- True iff the file corresponds to a test. 83 84 Derived classes must override this method.""" 85 86 raise NotImplementedError
87 88 # Methods that deal with suites. 89
90 - def GetSuite(self, suite_id):
91 """Return the 'Suite' for the suite named 'suite_id'. 92 93 'suite_id' -- A label naming the suite. 94 95 returns -- An instance of 'Suite' (or a derived class of 96 'Suite') corresponding to 'suite_id'. 97 98 raises -- 'NoSuchSuiteError' if there is no suite in the database 99 named 'suite_id'.""" 100 101 path = self.GetSuitePath(suite_id) 102 if not self._IsSuiteFile(path): 103 raise NoSuchSuiteError, suite_id 104 105 # There are two kinds of suites: directories (which are 106 # implicit suites), and files (which are explicit suites). 107 if os.path.isdir(path): 108 return DirectorySuite(self, suite_id) 109 else: 110 return self._GetSuiteFromPath(suite_id, os.path.normpath(path))
111 112
113 - def GetSuitePath(self, suite_id):
114 """Return the file containing 'suite_id'. 115 116 'suite_id' -- The name of a suite. 117 118 returns -- The absolute file name of the file (or directory) 119 that contains, or would contain, 'suite_id'. This method works 120 even if no suite named 'suite_id' exists. 121 122 Derived classes may override this method.""" 123 124 return self._GetPathFromLabel(suite_id)
125 126
127 - def _IsSuiteFile(self, path):
128 """Returns true if 'path' is a test suite file or directory. 129 130 'path' -- The absolute name of a file. All relevant 131 components in the path name have already been checked to 132 ensure that they are valid labels. 133 134 returns -- True iff the file corresponds to a test. 135 136 Derived classes may override this method, but only to restrict 137 the set of suites. In particular, a derived class method 138 may return false where this method would return true, but 139 never vice versa. 140 141 Derived classes must override this method.""" 142 143 raise NotImplementedError
144 145 # Methods that deal with resources. 146
147 - def GetResource(self, resource_id):
148 """Return the 'ResourceDescriptor' for the resource named 149 'resource_id'. 150 151 'resource_id' -- A label naming the resource. 152 153 returns -- A 'ResourceDescriptor' corresponding to 'resource_id'. 154 155 raises -- 'NoSuchResourceError' if there is no resource in the 156 database named 'resource_id'.""" 157 158 path = self.GetResourcePath(resource_id) 159 if not self._IsResourceFile(path): 160 raise NoSuchResourceError, resource_id 161 162 return self._GetResourceFromPath(resource_id, os.path.normpath(path))
163 164
165 - def GetResourcePath(self, resource_id):
166 """Return the file containing 'resource_id'. 167 168 'resource_id' -- The name of a resource. 169 170 returns -- The absolute file name of the file that contains, or 171 would contain, 'resource_id'. This method works even if no 172 Resource named 'resource_id' exists. 173 174 Derived classes may override this method.""" 175 176 return self._GetPathFromLabel(resource_id)
177 178
179 - def _IsResourceFile(self, path):
180 """Returns true if 'path' is a resource file. 181 182 'path' -- The absolute name of a file. All relevant 183 components in the path name have already been checked to 184 ensure that they are valid labels. 185 186 returns -- True iff the file corresponds to a resource. 187 188 Derived classes must override this method.""" 189 190 raise NotImplementedError
191 192 # Miscellaneous methods. 193
194 - def GetRoot(self):
195 """Return the root of the test database. 196 197 returns -- The directory that serves as the root of the test 198 database. All paths are relative to this directory. 199 200 Derived classes may override this method.""" 201 202 return self.GetPath()
203 204
205 - def GetSubdirectories(self, directory):
206 """Return the subdirectories of 'directory'. 207 208 'directory' -- A label indicating a directory in the database. 209 210 returns -- A sequence of (relative) labels indictating the 211 subdirectories of 'directory'. For example, if "a.b" and "a.c" 212 are directories in the database, this method will return "b" and 213 "c" given "a" as 'directory'.""" 214 215 subdirs = [] 216 file_dir = self.GetSuitePath(directory) 217 for entry in dircache.listdir(file_dir): 218 if not self._AreLabelsPaths(): 219 root = os.path.splitext(entry)[0] 220 else: 221 root = entry 222 if not self.IsValidLabel(root): 223 continue 224 entry_path = os.path.join(file_dir, entry) 225 if (self._IsSuiteFile(entry_path) 226 and os.path.isdir(entry_path)): 227 subdirs.append(root) 228 return subdirs
229 230
231 - def GetIds(self, kind, directory = "", scan_subdirs = 1):
232 233 # Compute the path name of the directory in which to start. 234 file_dir = self.GetSuitePath(directory) 235 # Get all the files of the appropriate kind. 236 return self._GetLabels(file_dir, scan_subdirs, directory, 237 lambda p: self._IsFile(kind, p))
238 239
240 - def _GetPath(self, kind, id):
241 """Returns the file system path corresponding to 'id'. 242 243 'kind' -- An extension kind. 244 245 'id' -- The name of the entity. 246 247 returns -- The path in which the entity is stored.""" 248 249 return { Database.RESOURCE : self.GetResourcePath, 250 Database.TEST : self.GetTestPath, 251 Database.SUITE : self.GetSuitePath } [kind] (id)
252 253
254 - def _IsFile(self, kind, path):
255 """Returns true if 'path' is a file of the indicated 'kind'. 256 257 'kind' -- One of 'Database.ITEM_KINDS'. 258 259 'path' -- The path to a file. 260 261 returns -- True iff 'path' is a file of the indicated kind. 262 263 Derived classes must override this method.""" 264 265 return { Database.TEST : self._IsTestFile, 266 Database.RESOURCE : self._IsResourceFile, 267 Database.SUITE : self._IsSuiteFile } [kind] (path)
268 269 # Derived classes must override these methods. 270
271 - def _GetTestFromPath(self, test_id, path):
272 """Return a descriptor for the test given by 'path'. 273 274 'test_id' -- The label naming the test. 275 276 'path' -- An absolute path to a test file. The 'path' satisfies 277 '_IsTestFile'. 278 279 returns -- A 'TestDescriptor' corresponding to 'test_id'. 280 281 Derived classes must override this method.""" 282 283 raise NotImplementedError
284 285
286 - def _GetSuiteFromPath(self, suite_id, path):
287 """Return a the 'Suite' given by 'path'. 288 289 'suite_id' -- The label naming the suite. 290 291 'path' -- An absolute path to a suite file. The 'path' 292 satisfies '_IsSuiteFile' and is a file, not a directory. 293 294 returns -- A 'Suite' corresponding to 'suite_id'. 295 296 Derived classes must override this method.""" 297 298 raise NotImplementedError
299 300
301 - def _GetResourceFromPath(self, resource_id, path):
302 """Return a descriptor for the resource given by 'path'. 303 304 'resource_id' -- The label naming the resource. 305 306 'path' -- An absolute path to a resource file. The 'path' 307 satisfies '_IsResourceFile'. 308 309 returns -- A 'ResourceDescriptor' corresponding to 310 'resource_id'. 311 312 Derived classes must override this method.""" 313 314 raise NotImplementedError
315 316
317 - def _GetPathFromLabel(self, label):
318 """Returns the file system path corresponding to 'label'. 319 320 'label' -- The id for a test, test suite, or similar entity. 321 322 returns -- The absolute path for the corresponding entry in 323 the file system, but without any required extension.""" 324 325 return os.path.join(self.GetRoot(), 326 self._GetRelativeLabelPath(label))
327 328
329 - def _GetLabelFromBasename(self, basename):
330 """Returns the label associated with a file named 'basename'. 331 332 'basename' -- The basename of a file, including the extension. 333 334 returns -- The corresponding label. 335 336 Derived classes may override this method.""" 337 338 return basename
339 340
341 - def _GetLabels(self, directory, scan_subdirs, label, predicate):
342 """Returns the labels of entities in 'directory'. 343 344 'directory' -- The absolute path name of the directory in 345 which to begin the search. 346 347 'scan_subdirs' -- True if (and only if) subdirectories of 348 'directory' should be scanned. 349 350 'label' -- The label that corresponds to 'directory'. 351 352 'predicate' -- A function that takes a file name and returns 353 a boolean. 354 355 returns -- Labels for all file names in 'directory'. that 356 satisfy 'predicate' If 'scan_subdirs' is true, subdirectories 357 are scanned as well.""" 358 359 labels = [] 360 361 # Go through all of the files (and subdirectories) in that 362 # directory. 363 for entry in dircache.listdir(directory): 364 entry_label = self._GetLabelFromBasename(entry) 365 # If the label is not valid then pretend it 366 # does not exist. It would not be valid to create an entity 367 # with such an id. 368 if not self.IsValidLabel(entry_label): 369 continue 370 # Compute the full path to 'entry'. 371 entry_path = os.path.join(directory, entry) 372 # If it satisfies the 'predicate', add it to the list. 373 if predicate(entry_path): 374 labels.append(self.JoinLabels(label, entry_label)) 375 # If it is a subdirectory, recurse. 376 if (scan_subdirs and os.path.isdir(entry_path) 377 and self._IsSuiteFile(entry_path)): 378 labels.extend(self._GetLabels(entry_path, 379 scan_subdirs, 380 self.JoinLabels(label, 381 entry_label), 382 predicate)) 383 384 return labels
385 386
387 - def RemoveExtension(self, id, kind):
388 389 path = self._GetPath(kind, id) 390 if not os.path.isfile(path): 391 raise { Database.RESOURCE : NoSuchResourceError, 392 Database.TEST: NoSuchTestError, 393 Database.SUITE: NoSuchSuiteError }[kind], id 394 395 os.remove(path)
396 397
398 - def _AreLabelsPaths(self):
399 """Returns true if labels are to be thought of as file names. 400 401 returns -- True if labels are to be thought of as file names. 402 If this predicate holds, every label is a path, relative to the 403 root of the database. If false, the labels are translated to 404 paths by adding the 'suite_extension' between directories and 405 the 'test_extension' or 'resource_extension' at the end of the 406 name.""" 407 408 return self.label_class == "file_label.FileLabel"
409 410
411 - def _GetRelativeLabelPath(self, label):
412 """Returns a representation of 'label' as a relative filename. 413 414 returns -- A relative filename corresponding to 'label'.""" 415 416 if self._AreLabelsPaths(): 417 return label 418 419 return os.path.join(*self.GetLabelComponents(label))
420 421 422
423 -class ExtensionDatabase(FileDatabase):
424 """An 'ExtensionDatabase' is a 'FileDatabase' where each kind of 425 entity (test, suite, resource) has a particular extension. For 426 example, if tests have the extension '.qmt', then all files ending 427 with '.qmt' are considered tests. If an extension for a particular 428 kind of entity is not specified or is the empty string, then all files 429 will be considered to be that kind of entity. 430 431 'ExtensionDatabase' is an abstract class.""" 432 433 arguments = [ 434 qm.fields.TextField( 435 name="test_extension", 436 title="Test Extension", 437 description="""The extension for test files. 438 439 The extension (including the leading period) used for files 440 containing tests.""", 441 default_value=".qmt"), 442 qm.fields.TextField( 443 name="suite_extension", 444 title="Suite Extension", 445 description="""The extension for suite files. 446 447 The extension (including the leading period) used for files 448 containing suites.""", 449 default_value=".qms"), 450 qm.fields.TextField( 451 name="resource_extension", 452 title="Resource Extension", 453 description="""The extension for resource files. 454 455 The extension (including the leading period) used for files 456 containing resources.""", 457 default_value=".qma"), 458 ] 459
460 - def __init__(self, path, arguments = None, **args):
461 462 super(ExtensionDatabase, self).__init__(path, arguments, **args) 463 self._extensions = { Database.TEST : self.test_extension, 464 Database.RESOURCE : self.resource_extension, 465 Database.SUITE : self.suite_extension }
466
467 - def GetTestExtension(self):
468 """Return the extension that indicates a file is a test. 469 470 returns -- The extension (including the leading period) that 471 indicates that a file is a test.""" 472 473 return self.test_extension
474 475
476 - def GetSuiteExtension(self):
477 """Return the extension that indicates a file is a suite. 478 479 returns -- The extension (including the leading period) that 480 indicates that a file is a suite.""" 481 482 return self.suite_extension
483 484
485 - def GetResourceExtension(self):
486 """Return the extension that indicates a file is a resource. 487 488 returns -- The extension (including the leading period) that 489 indicates that a file is a resource.""" 490 491 return self.resource_extension
492 493
494 - def GetTestPath(self, test_id):
495 496 test_path = self._GetPathFromLabel(test_id) 497 if not self._AreLabelsPaths(): 498 test_path += self.test_extension 499 return test_path
500 501
502 - def _IsTestFile(self, path):
503 504 extension = self.GetTestExtension() 505 if extension: 506 e = os.path.splitext(path)[1] 507 if e != extension: 508 return 0 509 510 return os.path.isfile(path)
511 512
513 - def GetSuitePath(self, suite_id):
514 515 # The top-level suite is just the directory containing the 516 # database; no extension is required. 517 if suite_id == "": 518 return self.GetRoot() 519 else: 520 suite_path = self._GetPathFromLabel(suite_id) 521 if not self._AreLabelsPaths(): 522 suite_path += self.suite_extension 523 return suite_path
524 525
526 - def _IsSuiteFile(self, path):
527 528 if path == self.GetRoot(): 529 return 1 530 531 extension = self.GetSuiteExtension() 532 if extension: 533 e = os.path.splitext(path)[1] 534 if e != extension: 535 return 0 536 537 return os.path.isfile(path) or os.path.isdir(path)
538 539
540 - def GetResourcePath(self, resource_id):
541 542 test_path = self._GetPathFromLabel(resource_id) 543 if not self._AreLabelsPaths(): 544 test_path += self.resource_extension 545 return test_path
546 547
548 - def _IsResourceFile(self, path):
549 550 extension = self.GetResourceExtension() 551 if extension: 552 e = os.path.splitext(path)[1] 553 if e != extension: 554 return 0 555 556 return os.path.isfile(path)
557 558
559 - def _GetPathFromLabel(self, label):
560 561 if self._AreLabelsPaths(): 562 path = label 563 else: 564 path = self._GetRelativeLabelPath(label) 565 566 return os.path.join(self.GetRoot(), path)
567 568
569 - def _GetLabelFromBasename(self, basename):
570 571 if self._AreLabelsPaths(): 572 return basename 573 else: 574 return os.path.splitext(basename)[0]
575 576
577 - def _GetRelativeLabelPath(self, label):
578 """Returns a representation of 'label' as a filename. 579 580 returns -- A filename corresponding to 'label'.""" 581 582 if self._AreLabelsPaths(): 583 return label 584 585 path = "" 586 components = self.GetLabelComponents(label) 587 if not components: 588 return path 589 590 for c in components[:-1]: 591 path = os.path.join(path, c + self.suite_extension) 592 path = os.path.join(path, components[-1]) 593 return path
594 595 596 ######################################################################## 597 # Local Variables: 598 # mode: python 599 # indent-tabs-mode: nil 600 # fill-column: 72 601 # End: 602

qmtest-2.4.1/share/doc/qmtest/html/manual/index.html0000664000076400007640000000111011122067163021761 0ustar stefanstefan API Documentation qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Var.Comment-class.html0000664000076400007640000002072011122067146032214 0ustar stefanstefan qm.external.DocumentTemplate.DT_Var.Comment
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Var :: Class Comment
[hide private]
[frames] | no frames]

Class Comment

source code

Comments

The 'comment' tag can be used to simply include comments in DTML source.

For example:

 <!--#comment-->

   This text is not rendered.

 <!--#/comment-->
Instance Methods [hide private]
 
__init__(self, args, fmt='') source code
 
render(self, md) source code
 
__call__(self, md) source code
Class Variables [hide private]
  name = 'comment'
  blockContinuations = ()
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test-pysrc.html0000664000076400007640000030040011122067152024363 0ustar stefanstefan qm.test.test
Package qm :: Package test :: Module test
[hide private]
[frames] | no frames]

Source Code for Module qm.test.test

  1  ######################################################################## 
  2  # 
  3  # File:   test.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2001-10-10 
  6  # 
  7  # Contents: 
  8  #   QMTest Test class. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  import qm.fields 
 22  import qm.test.database 
 23  import qm.test.result 
 24  import qm.test.runnable 
 25   
 26  ######################################################################## 
 27  # Variables 
 28  ######################################################################## 
 29   
 30  __the_targets = [] 
 31  """The global set of available targets.""" 
 32   
 33   
 34  ######################################################################## 
 35  # Classes 
 36  ######################################################################## 
 37   
38 -class TargetGroupField(qm.fields.TextField):
39 """A 'TargetGroupField' contains a target group pattern. 40 41 A target group pattern is a regular expression. A test will only be 42 run on a particular target if the target's group is matched by the 43 test's target group pattern.""" 44
45 - def GetDescription(self):
46 """Return a description of this field. 47 48 This description is used when displaying detailed help 49 information about the field.""" 50 51 # Get the basic description. 52 desc = qm.fields.TextField.GetDescription(self) 53 # Add a list of the available targets. 54 desc = desc + "\n\n**Available Target Groups**\n\n" 55 groups = [t.GetGroup() for t in get_targets()] 56 for g in groups: 57 desc = desc + " * " + g + "\n" 58 59 return desc
60 61 62
63 -class Test(qm.test.runnable.Runnable):
64 """A 'Test' is run to check for correct behavior. 65 66 A 'Test' performs some check on the system being tested, and 67 indicates whether the check was successful, or whether the 68 check failed. 69 70 Each test class (i.e., class derived from 'Test') describes a set 71 of "arguments". Each argument has a name and a type. The values 72 of these arguments determine the design-time parameters for the 73 test. For example, for a test class that executes program and 74 checks their exit codes, the arguments might consist of the 75 name of the program to execute, and the command-line arguments 76 that should be given to that program. QMTest uses the arguments 77 to prompt the user when creating a new test. 78 79 Each test class also defines a 'Run' method that indicates how 80 to run tests in that class. The 'Run' method is responsible for 81 actually performing the test and for reporting the results. 82 83 'Test' is an abstract class. 84 85 You can extend QMTest by providing your own test class 86 implementation. If the test classes that come with QMTest cannot 87 be used conveniently with your application domain, or if you would 88 like to report more detailed information about passing and failing 89 tests, you may wish to create a new test class. 90 91 To create your own test class, you must create a Python class 92 derived (directly or indirectly) from 'Test'. The documentation 93 for each method of 'Test' indicates whether you must override it 94 in your test class implementation. Some methods may be 95 overridden, but do not need to be. You might want to override 96 such a method to provide a more efficient implementation, but 97 QMTest will work fine if you just use the default version. 98 99 If QMTest calls a method on a test and that method raises an 100 exception that is not caught within the method itself, QMTest will 101 catch the exception and continue processing.""" 102
103 - class OutcomeField(qm.fields.EnumerationField):
104 """An 'OutcomeField' contains an outcome.""" 105
106 - def __init__(self, name, **properties):
116 117 118
119 - class TestField(qm.fields.ChoiceField):
120 """A 'TestField' contains the name of a test. 121 122 The exact format of the name depends on the test database in use.""" 123
124 - def GetItems(self):
125 126 database = qm.test.database.get_database() 127 return database.GetTestIds()
128 129 130 arguments = [ 131 TargetGroupField( 132 name="target_group", 133 title="Target Group Pattern", 134 description="""The targets on which this test can run. 135 136 A regular expression that indicates the targets on which 137 this test can be run. If the pattern matches a particular 138 group name, the test can be run on targets in that 139 group.""", 140 default_value=".*" 141 ), 142 qm.fields.SetField( 143 qm.fields.TupleField( 144 "prerequisites", 145 (TestField( 146 name = "test_id", 147 title = "Test", 148 description = """The name of the prerequisite test.""", 149 default_value = "", 150 ), 151 OutcomeField( 152 name = "outcome", 153 title = "Outcome", 154 description \ 155 = """The required outcome for the prerequisite test. 156 157 If the outcome is different from that given here, 158 the dependent test will not be run.""", 159 )), 160 title="Prerequisite Tests", 161 description="""The tests on which this test depends. 162 163 Every test can depend on other tests. Those tests will be 164 run before this test. If the prerequisite test does not 165 have the outcome indicated, this test will not be run.""", 166 )) 167 ] 168 169 kind = "test" 170 171 PREREQUISITES_FIELD_ID = "prerequisites" 172 """The name of the field that contains the prerequisites on which 173 this test depends.""" 174
175 - def Run(self, context, result):
176 """Run the test. 177 178 'context' -- A 'Context' giving run-time parameters to the 179 test. 180 181 'result' -- A 'Result' object. The outcome will be 182 'Result.PASS' when this method is called. The 'result' may be 183 modified by this method to indicate outcomes other than 184 'Result.PASS' or to add annotations. 185 186 This method should not return a value. 187 188 Derived classes must override this method.""" 189 190 raise NotImplementedError
191 192
193 - def GetTargetGroup(self):
194 """Returns the pattern for the targets that can run this test. 195 196 returns -- A regular expression (represented as a string) that 197 indicates the targets on which this test can be run. If the 198 pattern matches a particular group name, the test can be run 199 on targets in that group.""" 200 201 return self.target_group
202 203 204 ######################################################################## 205 # Functions 206 ######################################################################## 207
208 -def set_targets(targets):
209 """Set the available target. 210 211 'targets' -- A list of targets available for test execution.""" 212 213 global __the_targets 214 215 __the_targets = targets
216 217
218 -def get_targets():
219 """Get the available target. 220 221 returns -- A list of targets available for test execution.""" 222 223 return __the_targets
224 225 226 ######################################################################## 227 # Local Variables: 228 # mode: python 229 # indent-tabs-mode: nil 230 # fill-column: 72 231 # End: 232

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler_test-pysrc.html0000664000076400007640000047315611122067162027735 0ustar stefanstefan qm.test.classes.compiler_test
Package qm :: Package test :: Package classes :: Module compiler_test
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.compiler_test

  1  ######################################################################## 
  2  # 
  3  # File:   compiler_test.py 
  4  # Author: Mark Mitchell 
  5  # Date:   12/11/2001 
  6  # 
  7  # Contents: 
  8  #   CompilerTest 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  from   compiler import * 
 17  from   qm.test.result import * 
 18  from   qm.test.test import * 
 19  import os, dircache 
 20   
 21  ######################################################################## 
 22  # Classes 
 23  ######################################################################## 
 24   
25 -class CompilationStep:
26 """A single compilation step.""" 27
28 - def __init__(self, compiler, mode, files, options = [], ldflags = [], 29 output = None , diagnostics = []):
30 """Construct a new 'CompilationStep'. 31 32 'compiler' -- A Compiler object. 33 34 'mode' -- As for 'Compiler.Compile'. 35 36 'files' -- As for 'Compiler.Compile'. 37 38 'options' -- As for 'Compiler.Compile'. 39 40 'ldflags' -- As for 'Compiler.Compile'. 41 42 'output' -- As for 'Compiler.Compile'. 43 44 'diagnostics' -- A sequence of 'Diagnostic' instances 45 indicating diagnostic messages that are expected from this 46 compilation step.""" 47 48 self.compiler = compiler 49 self.mode = mode 50 self.files = files 51 self.options = options 52 self.ldflags = ldflags 53 self.output = output 54 self.diagnostics = diagnostics
55 56 57
58 -class CompilerBase:
59 """A 'CompilerBase' is used by compilation test and resource clases.""" 60
61 - def _GetDirectory(self, context):
62 """Get the name of the directory in which to run. 63 64 'context' -- A 'Context' giving run-time parameters to the 65 test. 66 67 'returns' -- The name of the directory in which this test or 68 resource will execute.""" 69 70 if context.has_key("CompilerTest.scratch_dir"): 71 return os.path.join(context["CompilerTest.scratch_dir"], 72 self.GetId()) 73 else: 74 return os.path.join(".", "build", self.GetId())
75 76
77 - def _MakeDirectory(self, context):
78 """Create a directory in which to place generated files. 79 80 'context' -- A 'Context' giving run-time parameters to the 81 test. 82 83 returns -- The name of the directory.""" 84 85 # Get the directory name. 86 directory = self._GetDirectory(context) 87 # Create it. 88 if not os.path.exists(directory): 89 os.makedirs(directory) 90 return directory
91 92
93 - def _RemoveDirectory(self, context, result):
94 """Remove the directory in which generated files are placed. 95 96 'result' -- The 'Result' of the test or resource. If the 97 'result' indicates success, the directory is removed. 98 Otherwise, the directory is left behind to allow investigation 99 of the reasons behind the test failure.""" 100 101 def removedir(directory, dir = True): 102 for n in dircache.listdir(directory): 103 name = os.path.join(directory, n) 104 if os.path.isfile(name): 105 os.remove(name) 106 elif os.path.isdir(name): 107 removedir(name) 108 if dir: os.rmdir(directory)
109 110 if result.GetOutcome() == Result.PASS: 111 try: 112 directory = self._GetDirectory(context) 113 removedir(directory, False) 114 os.removedirs(directory) 115 except: 116 # If the directory cannot be removed, that is no 117 # reason for the test to fail. 118 pass
119 120
121 - def _GetObjectFileName(self, source_file_name, object_extension):
122 """Return the default object file name for 'source_file_name'. 123 124 'source_file_name' -- A string giving the name of a source 125 file. 126 127 'object_extension' -- The extension used for object files. 128 129 returns -- The name of the object file that will be created by 130 compiling 'source_file_name'.""" 131 132 basename = os.path.basename(source_file_name) 133 return os.path.splitext(basename)[0] + object_extension
134 135 136
137 -class CompilerTest(Test, CompilerBase):
138 """A 'CompilerTest' tests a compiler.""" 139 140 _ignored_diagnostic_regexps = () 141 """A sequence of regular expressions matching diagnostics to ignore.""" 142
143 - def Run(self, context, result):
144 """Run the test. 145 146 'context' -- A 'Context' giving run-time parameters to the 147 test. 148 149 'result' -- A 'Result' object. The outcome will be 150 'Result.PASS' when this method is called. The 'result' may be 151 modified by this method to indicate outcomes other than 152 'Result.PASS' or to add annotations.""" 153 154 # If an executable is generated, executable_path will contain 155 # the generated path. 156 executable_path = None 157 # See what we need to run this test. 158 steps = self._GetCompilationSteps(context) 159 # See if we need to run this test. 160 is_execution_required = self._IsExecutionRequired() 161 # Create the temporary build directory. 162 self._MakeDirectory(context) 163 164 # Keep track of which compilation step we are performing so 165 # that we can annotate the result appropriately. 166 step_index = 1 167 168 # Perform each of the compilation steps. 169 for step in steps: 170 # Get the compiler to use for this test. 171 compiler = step.compiler 172 173 # Compute a prefix for the result annotations. 174 prefix = self._GetAnnotationPrefix() + "step_%d_" % step_index 175 176 # Get the compilation command. 177 command = compiler.GetCompilationCommand(step.mode, step.files, 178 step.options, 179 step.ldflags, 180 step.output) 181 result[prefix + "command"] = result.Quote(' '.join(command)) 182 # Run the compiler. 183 timeout = context.get("CompilerTest.compilation_timeout", -1) 184 (status, output) \ 185 = compiler.ExecuteCommand(self._GetDirectory(context), 186 command, timeout) 187 # Annotate the result with the output. 188 if output: 189 result[prefix + "output"] = result.Quote(output) 190 # Make sure that the output is OK. 191 if not self._CheckOutput(context, result, prefix, output, 192 step.diagnostics): 193 # If there were errors, do not try to run the program. 194 is_execution_required = 0 195 196 # Check the output status. 197 if step.mode == Compiler.MODE_LINK: 198 desc = "Link" 199 else: 200 desc = "Compilation" 201 # If step.diagnostics is non-empty, a non-zero status 202 # is not considered a failure. 203 if not result.CheckExitStatus(prefix, desc, status, 204 step.diagnostics): 205 return 206 207 # If this compilation generated an executable, remember 208 # that fact. 209 if step.mode == Compiler.MODE_LINK: 210 executable_path = os.path.join(".", step.output or "a.out") 211 212 # We're on to the next step. 213 step_index = step_index + 1 214 215 # Execute the generated program, if appropriate. 216 if executable_path and is_execution_required: 217 self._RunExecutable(executable_path, context, result)
218 219
220 - def _GetCompiler(self, context):
221 """Return the 'Compiler' to use. 222 223 'context' -- The 'Context' in which this test is being 224 executed.""" 225 226 raise NotImplementedError
227 228
229 - def _GetCompilationSteps(self, context):
230 """Return the compilation steps for this test. 231 232 'context' -- The 'Context' in which this test is being 233 executed. 234 235 returns -- A sequence of 'CompilationStep' objects.""" 236 237 raise NotImplementedError
238 239
240 - def _GetTarget(self, context):
241 """Returns a target for the executable to be run on. 242 243 'context' -- The Context in which this test is being executed. 244 245 returns -- A Host to run the executable on.""" 246 247 raise NotImplementedError
248 249
250 - def _IsExecutionRequired(self):
251 """Returns true if the generated executable should be run. 252 253 returns -- True if the generated executable should be run.""" 254 255 return 0
256 257
258 - def _GetExecutableArguments(self):
259 """Returns the arguments to the generated executable. 260 261 returns -- A list of strings, to be passed as argumensts to 262 the generated executable.""" 263 264 return []
265 266
268 """Returns true if the executable must exit with code zero. 269 270 returns -- True if the generated executable (if any) must exit 271 with code zero. Note that the executable will not be run at 272 all (and so the return value of this function will be ignored) 273 if '_IsExecutionRequired' does not return true.""" 274 275 return True
276 277
278 - def _GetAnnotationPrefix(self):
279 """Return the prefix to use for result annotations. 280 281 returns -- The prefix to use for result annotations.""" 282 283 return "CompilerTest."
284 285
286 - def _GetLibraryDirectories(self, context):
287 """Returns the directories to search for libraries. 288 289 'context' -- A 'Context' giving run-time parameters to the 290 test. 291 292 returns -- A sequence of strings giving the paths to the 293 directories to search for libraries.""" 294 295 return context.get("CompilerTest.library_dirs", "").split()
296 297
298 - def _RunExecutable(self, path, context, result):
299 """Run an executable generated by the compiler. 300 301 'path' -- The path to the generated executable. 302 303 'context' -- A 'Context' giving run-time parameters to the 304 test. 305 306 'result' -- A 'Result' object. The outcome will be 307 'Result.PASS' when this method is called. The 'result' may be 308 modified by this method to indicate outcomes other than 309 'Result.PASS' or to add annotations.""" 310 311 # Compute the result annotation prefix. 312 prefix = self._GetAnnotationPrefix() + "execution_" 313 # Record the command line. 314 path = os.path.join(self._GetDirectory(context), path) 315 arguments = self._GetExecutableArguments() 316 result[prefix + "command"] \ 317 = "<tt>" + path + " " + " ".join(arguments) + "</tt>" 318 319 # Compute the environment. 320 library_dirs = self._GetLibraryDirectories(context) 321 if library_dirs: 322 # Update LD_LIBRARY_PATH. On IRIX 6, this variable 323 # goes by other names, so we update them too. It is 324 # harmless to do this on other systems. 325 for variable in ['LD_LIBRARY_PATH', 326 'LD_LIBRARYN32_PATH', 327 'LD_LIBRARYN64_PATH']: 328 old_path = environment.get(variable) 329 new_path = ':'.join(self._library_dirs) 330 if old_path and new_path: 331 new_path = new_path + ':' + old_path 332 environment[variable] = new_path 333 else: 334 # Use the default values. 335 environment = None 336 337 target = self._GetTarget(context) 338 timeout = context.get("CompilerTest.execution_timeout", -1) 339 status, output = target.UploadAndRun(path, 340 arguments, 341 environment, 342 timeout) 343 # Record the output. 344 result[prefix + "output"] = result.Quote(output) 345 self._CheckExecutableOutput(result, output) 346 # Check the output status. 347 result.CheckExitStatus(prefix, "Executable", status, 348 not self._MustExecutableExitSuccessfully())
349 350
351 - def _CheckOutput(self, context, result, prefix, output, diagnostics):
352 """Check that the 'output' contains appropriate diagnostics. 353 354 'context' -- The 'Context' for the test that is being 355 executed. 356 357 'result' -- The 'Result' of the test. 358 359 'prefix' -- A string giving the prefix for any annotations to 360 be added to the 'result'. 361 362 'output' -- A string giving the output of the compiler. 363 364 'diagnostics' -- The diagnostics that are expected for the 365 compilation. 366 367 returns -- True if there were no errors so severe as to 368 prevent execution of the test.""" 369 370 # Get the compiler to use to parse the output. 371 compiler = self._GetCompiler(context) 372 373 # Parse the output. 374 emitted_diagnostics \ 375 = compiler.ParseOutput(output, self._ignored_diagnostic_regexps) 376 377 # Diagnostics that were not emitted, but should have been. 378 missing_diagnostics = [] 379 # Diagnostics that were emitted, but should not have been. 380 spurious_diagnostics = [] 381 # Expected diagnostics that have been matched. 382 matched_diagnostics = [] 383 # Keep track of any errors. 384 errors_occurred = 0 385 386 # Loop through the emitted diagnostics, trying to match each 387 # with an expected diagnostic. 388 for emitted_diagnostic in emitted_diagnostics: 389 # If the emitted diagnostic is an internal compiler error, 390 # then the test failed. (The compiler crashed.) 391 if emitted_diagnostic.severity == 'internal_error': 392 result.Fail("The compiler issued an internal error.") 393 return 0 394 if emitted_diagnostic.severity == "error": 395 errors_occurred = 1 396 # Assume that the emitted diagnostic is unexpected. 397 is_expected = 0 398 # Loop through the expected diagnostics, trying to find 399 # one that matches the emitted diagnostic. A single 400 # emitted diagnostic might match more than one expected 401 # diagnostic, so we can not break out of the loop early. 402 for expected_diagnostic in diagnostics: 403 if self._IsDiagnosticExpected(emitted_diagnostic, 404 expected_diagnostic): 405 matched_diagnostics.append(expected_diagnostic) 406 is_expected = 1 407 if not is_expected: 408 spurious_diagnostics.append(emitted_diagnostic) 409 # Any expected diagnostics for which there was no 410 # corresponding emitted diagnostic are missing diagnostics. 411 for expected_diagnostic in diagnostics: 412 if expected_diagnostic not in matched_diagnostics: 413 missing_diagnostics.append(expected_diagnostic) 414 415 # If there were missing or spurious diagnostics, the test failed. 416 if missing_diagnostics or spurious_diagnostics: 417 # Compute a succint description of what went wrong. 418 if missing_diagnostics and spurious_diagnostics: 419 result.Fail("Missing and spurious diagnostics.") 420 elif missing_diagnostics: 421 result.Fail("Missing diagnostics.") 422 else: 423 result.Fail("Spurious diagnostics.") 424 425 # Add annotations showing the problem. 426 if spurious_diagnostics: 427 self._DiagnosticsToString(result, 428 "spurious_diagnostics", 429 spurious_diagnostics) 430 if missing_diagnostics: 431 self._DiagnosticsToString(result, 432 "missing_diagnostics", 433 missing_diagnostics) 434 435 # If errors occurred, there is no point in trying to run 436 # the executable. 437 return not errors_occurred
438 439
440 - def _CheckExecutableOutput(self, result, output):
441 """Checks the output from the generated executable. 442 443 'result' -- The 'Result' object for this test. 444 445 'output' -- The output generated by the executable. 446 447 If the output is unsatisfactory, 'result' is modified 448 appropriately.""" 449 450 pass
451 452
453 - def _IsDiagnosticExpected(self, emitted, expected):
454 """Returns true if 'emitted' matches 'expected'. 455 456 'emitted' -- A 'Diagnostic emitted by the compiler. 457 458 'expected' -- A 'Diagnostic' indicating an expectation about a 459 diagnostic to be emitted by the compiler. 460 461 returns -- True if the 'emitted' was expected by the 462 'expected'.""" 463 464 # If the source positions do not match, there is no match. 465 if expected.source_position: 466 exsp = expected.source_position 467 emsp = emitted.source_position 468 469 if exsp.line and emsp.line != exsp.line: 470 return 0 471 if (exsp.file and (os.path.basename(emsp.file) 472 != os.path.basename(exsp.file))): 473 return 0 474 if exsp.column and emsp.column != exsp.column: 475 return 0 476 477 # If the severities do not match, there is no match. 478 if (expected.severity and emitted.severity != expected.severity): 479 return 0 480 # If the messages do not match, there is no match. 481 if expected.message and not re.search(expected.message, 482 emitted.message): 483 return 0 484 485 # There's a match. 486 return 1
487 488
489 - def _DiagnosticsToString(self, result, annotation, diagnostics):
490 """Return a string representing the 'diagnostics'. 491 492 'diagnostics' -- A sequence of 'Diagnostic' instances. 493 494 returns -- A string representing the 'Diagnostic's, with one 495 diagnostic message per line.""" 496 497 # Compute the string representation of each diagnostic. 498 diagnostic_strings = map(str, diagnostics) 499 # Insert a newline between each string. 500 result[self._GetAnnotationPrefix() + annotation] \ 501 = result.Quote("\n".join(diagnostic_strings))
502

././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_result_reader.FileResultReader.InvalidFile-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_result_reader.FileResultReader.InvalidFile-cl0000664000076400007640000001633411122067150033133 0ustar stefanstefan qm.test.file_result_reader.FileResultReader.InvalidFile
Package qm :: Package test :: Module file_result_reader :: Class FileResultReader :: Class InvalidFile
[hide private]
[frames] | no frames]

Class InvalidFile

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  FileResultReader.InvalidFile

An 'InvalidFile' exception indicates an incorrect file format.

If the constructor for a 'FileResultStream' detects an invalid file, it must raise an instance of this exception.

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.dejagnu_base-module.html0000664000076400007640000000214011122067144030360 0ustar stefanstefan dejagnu_base

Module dejagnu_base


Classes

DejaGNUBase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_In-module.html0000664000076400007640000000330611122067144031373 0ustar stefanstefan DT_In

Module DT_In


Classes

InClass
InFactory

Functions

basic_type
int_param

Variables

In
__rcs_id__

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate-module.html0000664000076400007640000002413511122067145033311 0ustar stefanstefan qm.external.DocumentTemplate.pDocumentTemplate
Package qm :: Package external :: Package DocumentTemplate :: Module pDocumentTemplate
[hide private]
[frames] | no frames]

Module pDocumentTemplate

source code

Python implementations of document template some features

$Id: pDocumentTemplate.py 1069 2008-11-13 21:55:43Z stefan $


Version: 1069

Classes [hide private]
  InstanceDict
  MultiMapping
  DictInstance
  TemplateDict
Functions [hide private]
True if D has a key k, else False
isFunctionType(D, k) source code
True if D has a key k, else False
isSimpleType(D, k) source code
 
render_blocks(blocks, md) source code
Variables [hide private]
  n = '__name__'
  name = 'UnboundMethodType'
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.WebServer-class.html0000664000076400007640000012567111122067151025071 0ustar stefanstefan qm.web.WebServer
Package qm :: Module web :: Class WebServer
[hide private]
[frames] | no frames]

Class WebServer

source code

SocketServer.BaseServer --+            
                          |            
     SocketServer.TCPServer --+        
                              |        
      BaseHTTPServer.HTTPServer --+    
                                  |    
                         HTTPServer --+
                                      |
                                     WebServer

A web server that serves ordinary files and dynamic content.

To configure the server to serve ordinary files, register the
directories containing those files with
'RegisterPathTranslations'.  An arbitrary number of directories
may  be specified, and all files in each directory and under it
are made available.

To congifure the server to serve dynamic content, register dynamic
URLs with 'RegisterScript'.  A request matching the URL exactly
will cause the server to invoke the provided function.

The web server resolves request URLs in a two-step process.

1. The server checks if the URL matches exactly a script URL.  If
   a match is found, the corresponding function is invoked, and
   its return value is sent to the client.

2. The server checks whether any registered path translation is a
   prefix of the reqest URL.  If it is, the path is translated
   into a file system path, and the corresponding file is
   returned.

The server also provides a rudimentary manual caching mechanism for
generated pages.  The application may insert a generated page into
the page cache, if it is expected not to change.  The application
can use this mechanism:

  - to supress duplicate generation of the same page,

  - or to pre-generate a page that may be requested later.  This is
    particularly handy if generating the page requires state
    information that would be difficult to reconstruct later.

Pages may be shared across sessions, or may be specific to a
particular session.

Instance Methods [hide private]
 
__init__(self, port, address='', log_file=sys.stdout)
Create a new web server.
source code
 
RegisterScript(self, script_path, script)
Register a dynamic URL.
source code
 
RegisterPathTranslation(self, url_path, file_path)
Register a path translation.
source code
 
IsScript(self, request)
Return a true value if 'request' corresponds to a script.
source code
 
ProcessScript(self, request)
Process 'request' as a script.
source code
 
TranslateRequest(self, request)
Translate the URL in 'request' to a file system path.
source code
 
Bind(self)
Bind the server to the specified address and port.
source code
 
Run(self)
Start the web server.
source code
 
RequestShutdown(self)
Shut the server down after processing the current request.
source code
 
LogMessage(self, message)
Log a message.
source code
 
GetServerAddress(self)
Return the host address on which this server is running.
source code
 
GetTemporaryAttachmentStore(self)
Return the 'AttachmentStore' used for new 'Attachment's.
source code
 
MakeButtonForCachedPopup(self, label, html_text, request=None, window_width=480, window_height=240)
Construct a button for displaying a cached popup page.
source code
 
MakeConfirmationDialog(self, message, url)
Generate JavaScript for a confirmation dialog box.
source code
 
MakePopupDialog(self, message, buttons, title='')
Generate JavaScript to show a popup dialog box.
source code
 
CachePage(self, page_text, session_id=None)
Cache an HTML page.
source code
 
GetCachedPage(self, request, session_id=None)
Retrieve a page from the page cache.
source code
 
__GetPathForCachedPage(self, request, session_id)
Return the path for a cached page.
source code
 
HandleNoSessionError(self, request, message)
Handler when session is absent.
source code
 
_HandleProblems(self, request)
Handle internal errors.
source code
 
_HandleRoot(self, request)
Handle the '/' URL.
source code
 
handle_error(self, request, client_address)
Handle an error gracefully.
source code

Inherited from HTTPServer: server_bind

Inherited from SocketServer.TCPServer: close_request, fileno, get_request, server_activate, server_close

Inherited from SocketServer.BaseServer: finish_request, handle_request, process_request, serve_forever, verify_request

Class Variables [hide private]

Inherited from BaseHTTPServer.HTTPServer: allow_reuse_address

Inherited from SocketServer.TCPServer: address_family, request_queue_size, socket_type

Method Details [hide private]

__init__(self, port, address='', log_file=sys.stdout)
(Constructor)

source code 

Create a new web server.

'port' -- The port on which to accept connections. If 'port' is '0', then any port will do.

'address' -- The local address to which to bind. An empty string means bind to all local addresses.

'log_file' -- A file object to which to write log messages. If it's 'None', no logging.

The server is not started until the 'Bind' and 'Run' methods are invoked.

Overrides: SocketServer.BaseServer.__init__

RegisterScript(self, script_path, script)

source code 
Register a dynamic URL.

'script_path' -- The URL for this script.  A request must
match this path exactly.

'script' -- A callable to invoke to generate the page
content.  

If you register

  web_server.RegisterScript('/cgi-bin/myscript', make_page)

then the URL 'http://my.server.com/cgi-bin/myscript' will
respond with the output of calling 'make_page'.

The script is passed a single argument, a 'WebRequest'
instance.  It returns the HTML source, as a string, of the
page it generates.  If it returns a tuple instead, the first
element is taken to be a MIME type and the second is the data.

The script may instead raise an 'HttpRedirect' instance,
indicating an HTTP redirect response should be sent to the
client.

RegisterPathTranslation(self, url_path, file_path)

source code 
Register a path translation.

'url_path' -- The path in URL-space to map from.  URLs of
which 'url_path' is a prefix can be translated.

'file_path' -- The file system path corresponding to
'url_path'.

For example, if you register

  web_server.RegisterPathTranslation('/images', '/path/to/pictures')

the URL 'http://my.server.com/images/big/tree.gif' will be
mapped to the file path '/path/to/pictures/big/tree.gif'.

ProcessScript(self, request)

source code 

Process 'request' as a script.

'request' -- A 'WebRequest' object.

returns -- The output of the script.

TranslateRequest(self, request)

source code 

Translate the URL in 'request' to a file system path.

'request' -- A 'WebRequest' object.

returns -- A path to the corresponding file, or 'None' if the request URL didn't match any translations.

Bind(self)

source code 

Bind the server to the specified address and port.

Does not start serving.

Run(self)

source code 

Start the web server.

preconditions -- The server must be bound.

GetServerAddress(self)

source code 

Return the host address on which this server is running.

returns -- A pair '(hostname, port)'.

GetTemporaryAttachmentStore(self)

source code 

Return the 'AttachmentStore' used for new 'Attachment's.

returns -- The 'AttachmentStore' used for new 'Attachment's.

MakeButtonForCachedPopup(self, label, html_text, request=None, window_width=480, window_height=240)

source code 

Construct a button for displaying a cached popup page.

'label' -- The button label.

'html_text' -- The HTML source for the popup page.

'window_width' -- The width, in pixels, of the popup window.

'window_height' -- The height, in pixels, of the popup window.

returns -- HTML source for the button. The button must be placed within a form element.

MakeConfirmationDialog(self, message, url)

source code 

Generate JavaScript for a confirmation dialog box.

'url' -- The location in the main browser window is set to the URL if the user confirms the action.

See 'make_popup_dialog_script' for a description of 'function_name' and 'message' and information on how to use the return value.

MakePopupDialog(self, message, buttons, title='')

source code 

Generate JavaScript to show a popup dialog box.

The popup dialog box displays a message and one or more buttons. Each button can have a JavaScript statement (or statements) associated with it; if the button is clicked, the statement is invoked. After any button is clicked, the popup window is closed as well.

'message' -- HTML source of the message to display in the popup window.

'buttons' -- A sequence of button specifications. Each is a pair '(caption, script)'. 'caption' is the button caption. 'script' is the JavaScript statement to invoke when the button is clicked, or 'None'.

'title' -- The popup window title.

returns -- JavaScript statements to show the dialog box, suiteable for use as an event handler.

CachePage(self, page_text, session_id=None)

source code 

Cache an HTML page.

'page_text' -- The text of the page.

'session_id' -- The session ID for this page, or 'None'.

returns -- A 'WebRequest' object with which the cached page can be retrieved later.

If 'session_id' is 'None', the page is placed in the global page cache. Otherwise, it is placed in the session page cache for that session.

GetCachedPage(self, request, session_id=None)

source code 

Retrieve a page from the page cache.

'request' -- The URL requesting the page from the cache.

'session_id' -- The session ID for the request, or 'None'.

returns -- The cached page, or a placeholder page if the page was not found in the cache.

If 'session_id' is 'None', the page is retrieved from the global page cache. Otherwise, it is retrieved from the session page cache for that session.

__GetPathForCachedPage(self, request, session_id)

source code 

Return the path for a cached page.

'request' -- The URL requesting the page from the cache.

'session_id' -- The session ID for the request, or 'None'.

handle_error(self, request, client_address)

source code 

Handle an error gracefully.

Overrides: SocketServer.BaseServer.handle_error

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.ItemDescriptor-class.html0000664000076400007640000005434111122067150030061 0ustar stefanstefan qm.test.database.ItemDescriptor
qm :: test :: database :: ItemDescriptor :: Class ItemDescriptor
[hide private]
[frames] | no frames]

Class ItemDescriptor

source code

Known Subclasses:

An 'ItemDescriptor' describes a test, resource, or similar entity.

Some 'Database' operations return an instance of a class derived from 'ItemDescriptor', rather than the object described. For example, 'Database.GetTest' returns a 'TestDescriptor', not a 'Test'. This additional indirection is an optimization; the creation of the actual 'Test' object may be relatively expensive, and in many cases all that is needed is information that can be gleaned from the descriptor.

Instance Methods [hide private]
 
__init__(self, database, instance_id, class_name=None, arguments=None, item=None)
Construct an 'ItemDescriptor'.
source code
 
GetDatabase(self)
Return the 'Database' containing this entity.
source code
 
GetClassName(self)
Return the class name of the entity.
source code
 
GetClass(self)
Return the class of the entity.
source code
 
GetClassArguments(self)
Return the arguments specified by the test class.
source code
 
GetArguments(self)
Return the entity arguments.
source code
 
GetId(self)
Return the label for this entity.
source code
 
GetItem(self)
Return the entity.
source code
 
GetResources(self)
Return the resources required by this item.
source code
 
_Execute(self, context, result, method)
Execute the entity.
source code
Method Details [hide private]

__init__(self, database, instance_id, class_name=None, arguments=None, item=None)
(Constructor)

source code 

Construct an 'ItemDescriptor'.

'database' -- The 'Database' object in which this entity is located.

'instance_id' -- The label for this entity.

'class_name' -- The name of the extension class for the entity. For example, for a 'TestDescriptor', the 'class_name' is the name of the test class. Omit this argument if 'item' is provided.

'arguments' -- A dictionary mapping argument names to argument values. These arguments will be provided to the extension class when the entity is constructed. Omit this argument if 'item' is provided.

'item' -- The item class for this item instance.

GetDatabase(self)

source code 

Return the 'Database' containing this entity.

returns -- The 'Database' object in which this entity is located.

GetClassName(self)

source code 

Return the class name of the entity.

returns -- The name of the extension class for the entity. For example, for a 'TestDescriptor', this method returns the name of the test class.

GetClass(self)

source code 

Return the class of the entity.

returns -- The Python class object for the entity. For example, for a 'TestDescriptor', this method returns the test class.

GetClassArguments(self)

source code 

Return the arguments specified by the test class.

returns -- A list of 'Field' objects containing all the arguments in the class hierarchy.

Derived classes should not override this method.

GetArguments(self)

source code 

Return the entity arguments.

returns -- A dictionary mapping argument names to argument values. These arguments will be provided to the extension class when the entity is constructed.

GetId(self)

source code 

Return the label for this entity.

returns -- The label for this entity.

GetItem(self)

source code 

Return the entity.

returns -- An instance of the class returned by 'GetClass'.

GetResources(self)

source code 

Return the resources required by this item.

returns -- A sequence of resource names. Each name indicates a resource that must be available to this item.

_Execute(self, context, result, method)

source code 

Execute the entity.

'context' -- The 'Context' in which the test should be executed, or 'None' if the 'method' does not take a 'Context' argument.

'result' -- The 'Result' object corresponding to this execution.

'method' -- The method name of the method on the entity that should be invoked to perform the execution.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.temporary-module.html0000664000076400007640000000215311122067144027777 0ustar stefanstefan temporary

Module temporary


Classes

TempDirectoryResource

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command_host-pysrc.html0000664000076400007640000007630011122067162027525 0ustar stefanstefan qm.test.classes.command_host
Package qm :: Package test :: Package classes :: Module command_host
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.command_host

 1  ######################################################################## 
 2  # 
 3  # File:   command_host.py 
 4  # Author: Stefan Seefeld 
 5  # Date:   2006-10-24 
 6  # 
 7  # Contents: 
 8  #   CommandHost 
 9  # 
10  # Copyright (c) 2006 by CodeSourcery, Inc.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ####################################################################### 
17   
18  from qm.fields import TextField, SetField 
19  from qm.test.classes import local_host 
20  import sys, os, os.path 
21   
22  ######################################################################## 
23  # Classes 
24  ####################################################################### 
25   
26 -class CommandHost(local_host.LocalHost):
27 """A CommandHost runs an executable through a command. 28 29 The 'command' parameter specifies the command to use, while 30 'command_args' contains a set of arguments to be passed to the 31 command.""" 32 33 34 command = TextField(description="Name of the command" 35 " used to run the executable.") 36 command_args = SetField(TextField(description="Set of arguments" 37 " passed to the command.")) 38
39 - def Run(self, path, arguments, environment = None, timeout = -1, 40 relative = False):
41 42 if (relative 43 or (not os.path.isabs(path) 44 and (path.find(os.path.sep) != -1 45 or (os.path.altsep 46 and path.find(os.path.altsep) != -1)))): 47 path = os.path.join(os.curdir, path) 48 arguments = self.command_args + [path] + arguments 49 return local_host.LocalHost.Run(self, self.command, 50 arguments, environment, timeout)
51

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.context.ContextWrapper-class.html0000664000076400007640000001012711122067150030023 0ustar stefanstefan qm.test.context.ContextWrapper
Package qm :: Package test :: Module context :: Class ContextWrapper
[hide private]
[frames] | no frames]

Class ContextWrapper

source code

Do-nothing class to preserve pickle compatability.

A class called 'ContextWrapper' used to be used in instead of a 'Context' class in some cases, and we used to put contexts into 'Result's. Because of how pickles work, this means that the only way to unpickle these old 'Result's is to have a do-nothing placeholder class that can be instantiated and then thrown away.

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.xml_result_stream-module.html0000664000076400007640000000236411122067144031532 0ustar stefanstefan xml_result_stream

Module xml_result_stream


Classes

XMLResultReader
XMLResultStream

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.run_database-module.html0000664000076400007640000000213011122067144026744 0ustar stefanstefan run_database

Module run_database


Classes

RunDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_If.If-class.html0000664000076400007640000001700211122067146030755 0ustar stefanstefan qm.external.DocumentTemplate.DT_If.If
Package qm :: Package external :: Package DocumentTemplate :: Module DT_If :: Class If
[hide private]
[frames] | no frames]

Class If

source code

Instance Methods [hide private]
 
__init__(self, blocks) source code
Class Variables [hide private]
  blockContinuations = ('else', 'elif')
  name = 'if'
  elses = None
  expr = ''
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.attachment-pysrc.html0000664000076400007640000043754111122067152024577 0ustar stefanstefan qm.attachment
Package qm :: Module attachment
[hide private]
[frames] | no frames]

Source Code for Module qm.attachment

  1  ######################################################################## 
  2  # 
  3  # File:   attachment.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-03-21 
  6  # 
  7  # Contents: 
  8  #   Generic code for handling arbitrary file attachments. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  """Code for handling arbitrary file attachments. 
 17   
 18  'Attachment' is a base class for classes that represent arbitrary 
 19  attachments.  Each 'Attachment' object has these four attributes: 
 20   
 21    'mime_type' -- The MIME type of the attachment contents.  This 
 22    information enables user interfaces to handle attachment data in a 
 23    sensible fasion. 
 24   
 25    'description' -- The user's description of the attachment contents. 
 26   
 27    'file_name' -- A file name associated with the description.  This is 
 28    usually the name of the file from which the attachment was originally 
 29    uploaded or inserted. 
 30   
 31    'location' -- A string containing the external location of the 
 32    attachment data.  The semantics of this string are defined by 
 33    implementations of 'AttachmentStore', which use it to locate the 
 34    attachment's data. 
 35   
 36  A special 'TemporaryAttachmentStore', with a different interface, is 
 37  used to store attachment data temporarily, at most for the life of the 
 38  program.  The 'temporary_store' global instance should be used."""  
 39   
 40  ######################################################################## 
 41  # imports 
 42  ######################################################################## 
 43   
 44  import common 
 45  import mimetypes 
 46  import os 
 47  import xmlutil 
 48  import temporary_directory 
 49   
 50  ######################################################################## 
 51  # classes 
 52  ######################################################################## 
 53   
54 -class Attachment:
55 """An arbitrary file attachment. 56 57 Conceptually, an attachment is composed of these parts: 58 59 1. A MIME type, as a string. 60 61 2. A description, as a structured text string. 62 63 3. A file name, corresponding to the original name of the file from 64 which the attachment was uploaded, or the name of the file to 65 use when the attachment is presented to the user in a file 66 system. 67 68 4. A block of arbitrary data. 69 70 For efficiency reasons, the attachment data is not stored in the 71 attachment. Instead, a *location* is stored, which is a key into 72 the associated 'AttachmentStore' object.""" 73
74 - def __init__(self, 75 mime_type, 76 description, 77 file_name, 78 location, 79 store):
80 """Create a new attachment. 81 82 'mime_type' -- The MIME type. If 'None' or an empty string, the 83 function attempts to guess the MIME type from other information. 84 85 'description' -- A description of the attachment contents. 86 87 'file_name' -- The user-visible file name to associate the 88 attachment. 89 90 'location' -- The location in an attachment store at which to 91 find the attachment data. 92 93 'store' -- The attachment store in which the data is stored.""" 94 95 # If no MIME type is specified, try to guess it from the file 96 # name. 97 if mime_type == "" or mime_type is None: 98 mime_type = mimetypes.guess_type(file_name)[0] 99 if mime_type is None: 100 # Couldn't guess from the file name. Use a safe 101 # default. 102 mime_type = "application/octet-stream" 103 self.__mime_type = mime_type 104 # Store other attributes. 105 self.__description = description 106 self.__file_name = file_name 107 self.__location = location 108 self.__store = store
109 110
111 - def GetMimeType(self):
112 """Return the attachment's MIME type.""" 113 114 return self.__mime_type
115 116
117 - def GetDescription(self):
118 """Return the attachment's description.""" 119 120 return self.__description
121 122
123 - def GetFileName(self):
124 """Return the attachment's file name.""" 125 126 return self.__file_name
127 128
129 - def GetLocation(self):
130 """Return the attachment's location in an attachment store.""" 131 132 return self.__location
133 134
135 - def GetData(self):
136 """Get attachment data. 137 138 returns -- The attachment data.""" 139 140 return self.GetStore().GetData(self.GetLocation())
141 142
143 - def GetDataFile(self):
144 """Return the path to a file containing attachment data. 145 146 returns -- A file system path. The file should be considered 147 read-only, and should not be modified in any way.""" 148 149 return self.GetStore().GetDataFile(self.GetLocation())
150 151
152 - def GetStore(self):
153 """Return the store in which this attachment is located. 154 155 returns -- The 'AttachmentStore' that contains this attachment.""" 156 157 return self.__store
158 159
160 - def Move(self, store, location):
161 """Move the 'Attachment' to a new location. 162 163 'store' -- The 'AttachmentStore' that will contain the 164 attachment. 165 166 'location' -- The location of the attachment within its current 167 store.""" 168 169 # Store this attachment in its new location. That must be done 170 # before removing it from its current location as that step will 171 # destroy the data contained in the attachment. 172 store.Store(self, location) 173 # Now, remove the attachment from its current location. 174 self.__store.Remove(self.__location) 175 # Finally, update the information associated with the attachment. 176 self.__store = store 177 self.__location = location
178 179
180 - def __str__(self):
181 return '<Attachment "%s" (%s)>' \ 182 % (self.GetDescription(), self.GetMimeType())
183 184
185 - def __cmp__(self, other):
186 return other is None \ 187 or self.GetDescription() != other.GetDescription() \ 188 or self.GetMimeType() != other.GetMimeType() \ 189 or self.GetFileName() != other.GetFileName() \ 190 or self.GetLocation() != other.GetLocation() \ 191 or self.GetStore() != other.GetStore()
192 193 194
195 -class AttachmentStore(object):
196 """Interface for classes which store attachment data. 197 198 An attachment store stores the raw data for an attachment. The 199 store is not responsible for storing auxiliary information, 200 including the attachment's description, file name, or MIME type. 201 202 Users of an 'AttachmentStore' reference attachment data by a 203 *location*, which is stored with the attachment. 204 205 Please note that the 'AttachmentStore' interface provides methods 206 for retrieving attachment data only; not for storing it. The 207 interface for storing may be defined in any way by implementations.""" 208
209 - def GetData(self, location):
210 """Return the data for an attachment. 211 212 returns -- A string containing the attachment data.""" 213 214 raise NotImplementedError
215 216
217 - def GetDataFile(self, location):
218 """Return the path to a file containing the data for 219 'attachment'. 220 221 returns -- A file system path. 222 223 The file is read-only, and may be a temporary file. The caller 224 should not modify the file in any way.""" 225 226 raise NotImplementedError
227 228
229 - def GetSize(self, location):
230 """Return the size of the data for an attachment. 231 232 returns -- The length of the attachment data, in bytes. 233 234 This method may be overridden by derived classes.""" 235 236 return len(self.GetData(location))
237 238
239 - def HandleDownloadRequest(self, request):
240 """Handle a web request to download attachment data. 241 242 'request' -- A 'WebRequest' object. The location of the 243 attachment data is stored in the 'location' property, and the 244 MIME type in the 'mime_type' property. 245 246 returns -- A pair '(mime_type, data)' where 'mime_type' is the 247 MIME type stored in the request and 'data' is the contents of 248 the attachment.""" 249 250 location = request["location"] 251 mime_type = request["mime_type"] 252 data = self.GetData(location) 253 return (mime_type, data)
254 255
256 - def Store(self, attachment, location):
257 """Add an attachment to the store. 258 259 'attachment' -- The 'Attachment' to store. 260 261 'location' -- The location in which to store the 'attachment'.""" 262 263 raise NotImplementedError
264 265 266
267 -class FileAttachmentStore(AttachmentStore):
268 """An attachment store based on the file system. 269 270 The locations are the names of files in the file system.""" 271
272 - def __init__(self, root = None):
273 """Construct a new 'FileAttachmentStore' 274 275 'root' -- If not 'None', the root directory for the store. All 276 locations are relative to this directory. If 'None', all 277 locations are relative to the current directory.""" 278 279 super(AttachmentStore, self).__init__() 280 self.__root = root
281 282
283 - def GetData(self, location):
284 285 # Open the file. 286 f = open(self.GetDataFile(location)) 287 # Read the contents. 288 s = f.read() 289 # Close the file. 290 f.close() 291 292 return s
293 294
295 - def GetDataFile(self, location):
296 297 if self.__root is not None: 298 # It might seem sensible to assert that the location be a 299 # relative path, but that would break backwards 300 # compatibility with older versions fo QMTest. In those 301 # older versions, the XMLDatabase sometimes used an absolute 302 # path for attachment locations. 303 return os.path.join(self.__root, location) 304 else: 305 return location
306 307
308 - def GetSize(self, location):
309 310 return os.stat(self.GetDataFile(location))[6]
311 312
313 - def Store(self, attachment, location):
314 315 # Create the file. 316 file = open(self.GetDataFile(location), "w") 317 # Write the data. 318 file.write(attachment.GetData()) 319 # Close the file. 320 file.close()
321 322
323 - def Remove(self, location):
324 """Remove an attachment. 325 326 'location' -- The location whose data should be removed.""" 327 328 os.remove(self.GetDataFile(location))
329 330 331
332 -class TemporaryAttachmentStore(FileAttachmentStore):
333 """Temporary storage for attachment data. 334 335 A 'TemporaryAttachmentStore' stores attachment data in a temporary 336 location, for up to the lifetime of the running program. When the 337 program ends, all temporarily stored attachment data is deleted. 338 339 A data object in the temporary store is identified by its location. 340 Locations should be generated by 'make_temporary_location'.""" 341
342 - def __init__(self):
343 """Construct a temporary attachment store. 344 345 The store is initially empty.""" 346 347 # Construct a temporary directory in which to store attachment 348 # data. 349 self.__tmpdir = temporary_directory.TemporaryDirectory() 350 # Initialize the base class. 351 path = self.__tmpdir.GetPath() 352 super(TemporaryAttachmentStore, self).__init__(path)
353 354
355 - def HandleUploadRequest(self, request):
356 """Handle a web request to upload attachment data. 357 358 Store the attachment data contained in the request as a 359 temporary attachment. It is assumed that the request is being 360 submitted from a popup upload browser window, so the returned 361 HTML page instructs the window to close itself. 362 363 'request' -- A 'WebRequest' object. 364 365 returns -- HTML text of a page that instructs the browser window 366 to close.""" 367 368 location = request["location"] 369 # Create the file. 370 file = open(self.GetDataFile(location), "w") 371 # Write the data. 372 file.write(request["file_data"]) 373 # Close the file. 374 file.close() 375 # Return a page that closes the popup window from which the 376 # attachment was submitted. 377 return ''' 378 <html><body> 379 <script type="text/javascript" language="JavaScript"> 380 window.close(); 381 </script> 382 </body></html> 383 '''
384 385 ######################################################################## 386 # functions 387 ######################################################################## 388 389 _temporary_location_prefix = "_temporary" 390 391
393 """Return a unique location for temporary attachment data.""" 394 395 return _temporary_location_prefix + common.make_unique_tag()
396 397
398 -def make_dom_node(attachment, document):
399 """Create a DOM element node for this attachment. 400 401 'document' -- A DOM document node in which to create the 402 element. 403 404 returns -- A DOM element node.""" 405 406 # Create an attachment element. 407 node = document.createElement("attachment") 408 # Is it a null attachment? 409 if attachment is None: 410 # Then that's it. 411 return node 412 413 mime_type = attachment.GetMimeType() 414 415 # Create and add the description node. 416 child = xmlutil.create_dom_text_element( 417 document, "description", attachment.GetDescription()) 418 node.appendChild(child) 419 # Create and add the MIME type node. 420 child = xmlutil.create_dom_text_element( 421 document, "mime-type", mime_type) 422 node.appendChild(child) 423 # Create and add the file name node. 424 child = xmlutil.create_dom_text_element( 425 document, "filename", attachment.GetFileName()) 426 node.appendChild(child) 427 # Create a location element, to include attachment data by 428 # reference. 429 location = attachment.GetLocation() 430 child = xmlutil.create_dom_text_element(document, "location", location) 431 432 node.appendChild(child) 433 return node
434 435
436 -def from_dom_node(node, store):
437 """Construct an attachment object from a DOM element node. 438 439 'node' -- A DOM attachment element node. 440 441 'store' -- The associated attachment store. 442 443 returns -- An attachment instance. The type is determined by 444 'attachment_class'. 445 446 If the attachment object requires additional context information to 447 interpret the location (if it's specified in the attachment 448 element), the caller must provide it directly to the object.""" 449 450 if len(node.childNodes) == 0: 451 # It's an empty element, signifying a null attachment. 452 return None 453 454 # Extract the fixed fields; use a default value for each that is not 455 # present. 456 description = xmlutil.get_child_text(node, "description", "") 457 mime_type = xmlutil.get_child_text( 458 node, "mime-type", "application/octet-stream") 459 file_name = xmlutil.get_child_text(node, "filename", "") 460 location = xmlutil.get_child_text(node, "location") 461 # Construct the resulting attachment. 462 return Attachment(mime_type, description, file_name, location, store)
463 464 ######################################################################## 465 # Local Variables: 466 # mode: python 467 # indent-tabs-mode: nil 468 # fill-column: 72 469 # End: 470

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.runnable-pysrc.html0000664000076400007640000023603111122067152025222 0ustar stefanstefan qm.test.runnable
Package qm :: Package test :: Module runnable
[hide private]
[frames] | no frames]

Source Code for Module qm.test.runnable

  1  ######################################################################## 
  2  # 
  3  # File:   runnable.py 
  4  # Author: Mark Mitchell 
  5  # Date:   10/11/2002 
  6  # 
  7  # Contents: 
  8  #   QMTest Runnable class. 
  9  # 
 10  # Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  import qm.extension 
 22  from   qm.fields import AttachmentField, TupleField, SetField 
 23   
 24  ######################################################################## 
 25  # Classes 
 26  ######################################################################## 
 27   
28 -class Runnable(qm.extension.Extension):
29 """A 'Runnable' can run on a 'Target'. 30 31 'Runnable' is an abstract base class for 'Test' and 'Resource'.""" 32
33 - class ResourceField(qm.fields.ChoiceField):
34 """A 'ResourceField' contains the name of a resource. 35 36 The exact format of the name depends on the test database in use.""" 37
38 - def GetItems(self):
42 43 44 45 EXTRA_ID = "qmtest_id" 46 """The name of the extra keyword argument to '__init__' that 47 specifies the name of the test or resource.""" 48 49 EXTRA_DATABASE = "qmtest_database" 50 """The name of the extra keyword argument to '__init__' that 51 specifies the database containing the test or resource.""" 52 53 RESOURCE_FIELD_ID = "resources" 54 """The name of the field that contains the resources on which this 55 test or resource depends.""" 56 57 arguments = [ 58 qm.fields.SetField( 59 ResourceField( 60 name = RESOURCE_FIELD_ID, 61 title = "Resources", 62 description = \ 63 """Resources on which this test or resource depends. 64 65 Before this test or resource is executed, the 66 resources on which it depends will be set up.""", 67 not_empty_text = "true", 68 )), 69 ] 70 71
72 - def __init__(self, arguments = None, **args):
73 """Construct a new 'Runnable'. 74 75 'arguments' -- As for 'Extension.__init__'. 76 77 'args' -- As for 'Extension.__init__.""" 78 79 self.__id = args.pop(self.EXTRA_ID) 80 self.__database = args.pop(self.EXTRA_DATABASE) 81 if arguments: args.update(arguments) 82 super(Runnable, self).__init__(**args)
83 84 85
86 - def GetId(self):
87 """Return the name of this test or resource. 88 89 'context' -- The 'Context' in which this entity is running. 90 91 returns -- The name of this test or resource.""" 92 93 return self.__id
94 95
96 - def GetDatabase(self):
97 """Return the 'Database' in which this test or resource is stored. 98 99 returns -- The 'Database' in which this test or resource is 100 stored.""" 101 102 return self.__database
103 104
105 - def GetAttachments(self):
106 """Return the 'Attachment's to this 'Runnable'. 107 108 returns -- A sequence consisting of the 'Attachment' objects 109 associated with this runnable.""" 110 111 attachments = [] 112 for f in qm.extension.get_class_arguments(self.__class__): 113 self.__GetAttachments(f, 114 getattr(self, f.GetName()), 115 attachments) 116 return attachments
117 118
119 - def __GetAttachments(self, field, value, attachments):
120 """Return the 'Attachments' that are part of 'field'. 121 122 'field' -- The 'Field' being examined. 123 124 'value' -- The value of that 'Field' in 'self'. 125 126 'attachments' -- A sequence consisting of the attachments 127 found so far. Additional 'Attachment's are appended to this 128 sequence by this function.""" 129 130 if isinstance(field, AttachmentField): 131 attachments.append(getattr(self, field.GetName())) 132 elif isinstance(field, TupleField): 133 subfields = field.GetSubfields() 134 for i in xrange(len(subfields)): 135 self.__GetAttachments(subfields[i], value[i], 136 attachments) 137 elif isinstance(field, SetField): 138 subfield = field.GetSubfields()[0] 139 for i in xrange(len(value)): 140 self.__GetAttachments(subfield, value[i], 141 attachments) 142 143 return
144

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Var.Var-class.html0000664000076400007640000002013411122067146031341 0ustar stefanstefan qm.external.DocumentTemplate.DT_Var.Var
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Var :: Class Var
[hide private]
[frames] | no frames]

Class Var

source code

Instance Methods [hide private]
 
__init__(self, args, fmt='s') source code
 
render(self, md) source code
 
__call__(self, md) source code
Class Variables [hide private]
  name = 'var'
  expr = None
qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-M.html0000664000076400007640000007533211122067144024313 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

M



qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.dist.command-module.html0000664000076400007640000000170711122067144025727 0ustar stefanstefan command

Module command



[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.command-module.html0000664000076400007640000000264011122067144027374 0ustar stefanstefan command

Module command


Classes

ExecTest
ExecTestBase
ShellCommandTest
ShellScriptTest

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.AttachmentField-class.html0000664000076400007640000010062611122067146026707 0ustar stefanstefan qm.fields.AttachmentField
qm :: fields :: AttachmentField :: Class AttachmentField
[hide private]
[frames] | no frames]

Class AttachmentField

source code

object --+    
         |    
     Field --+
             |
            AttachmentField

A field containing a file attachment.

Note that the 'FormatValueAsHtml' method uses a popup upload form for uploading new attachment. The web server must be configured to handle the attachment submission requests. See 'attachment.register_attachment_upload_script'.

Instance Methods [hide private]
 
__init__(self, name='', **properties)
Create an attachment field.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
GetHtmlHelp(self, edit=0)
Generate help text about this field in HTML format.
source code
 
FormatValueAsText(self, value, columns=72)
Return a plain text rendering of a 'value' for this field.
source code
 
FormatValueAsHtml(self, server, value, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
MakeDomNodeForValue(self, value, document)
Generate a DOM element node for a value of this field.
source code
 
_FormatSummary(self, attachment)
Generate a user-friendly summary for 'attachment'.
source code
 
Validate(self, value)
Validate a field value.
source code
 
ParseFormValue(self, request, name, attachment_stores)
Convert a value submitted from an HTML form.
source code
 
GetValueFromDomNode(self, node, attachment_store)
Return a value for this field represented by DOM 'node'.
source code

Inherited from Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, ParseTextValue, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]
  upload_url = '/attachment-upload'
The URL used to upload data for an attachment.
  download_url = '/attachment-download'
The URL used to download an attachment.

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', **properties)
(Constructor)

source code 

Create an attachment field.

Sets the default value of the field to 'None'.

Overrides: object.__init__

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: Field.GetHelp
(inherited documentation)

GetHtmlHelp(self, edit=0)

source code 

Generate help text about this field in HTML format.

'edit' -- If true, display information about editing controls for this field.

Overrides: Field.GetHtmlHelp
(inherited documentation)

FormatValueAsText(self, value, columns=72)

source code 

Return a plain text rendering of a 'value' for this field.

'columns' -- The maximum width of each line of text.

returns -- A plain-text string representing 'value'.

Overrides: Field.FormatValueAsText
(inherited documentation)

FormatValueAsHtml(self, server, value, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

Overrides: Field.FormatValueAsHtml
(inherited documentation)

MakeDomNodeForValue(self, value, document)

source code 

Generate a DOM element node for a value of this field.

'value' -- The value to represent.

'document' -- The containing DOM document node.

Overrides: Field.MakeDomNodeForValue
(inherited documentation)

_FormatSummary(self, attachment)

source code 

Generate a user-friendly summary for 'attachment'.

This value is used when generating the form. It can't be editied.

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

Overrides: Field.Validate
(inherited documentation)

ParseFormValue(self, request, name, attachment_stores)

source code 

Convert a value submitted from an HTML form.

'request' -- The 'WebRequest' containing a value corresponding to this field.

'name' -- The name corresponding to this field in the 'request'.

'attachment_stores' -- A dictionary mapping 'AttachmentStore' ids (in the sense of Python's 'id' built-in) to the 'AttachmentStore's themselves.

returns -- A pair '(value, redisplay)'. 'value' is the value for this field, as indicated in 'request'. 'redisplay' is true if and only if the form should be redisplayed, rather than committed. If an error occurs, an exception is thrown.

Overrides: Field.ParseFormValue
(inherited documentation)

GetValueFromDomNode(self, node, attachment_store)

source code 

Return a value for this field represented by DOM 'node'.

This method does not validate the value for this particular instance; it only makes sure the node is well-formed, and returns a value of the correct Python type.

'node' -- The DOM node that is being evaluated.

'attachment_store' -- For attachments, the store that should be used.

If the 'node' is incorrectly formed, this method should raise an exception.

Overrides: Field.GetValueFromDomNode
(inherited documentation)

Class Variable Details [hide private]

upload_url

The URL used to upload data for an attachment.

The upload request will include these query arguments:

  'location' -- The location at which to store the attachment data.

  'file_data' -- The attachment data.

Value:
'/attachment-upload'

download_url

The URL used to download an attachment.

The download request will include this query argument:

  'location' -- The location in the attachment store from which to
  retrieve the attachment data.

Value:
'/attachment-download'

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.process_target-pysrc.html0000664000076400007640000033377511122067163030113 0ustar stefanstefan qm.test.classes.process_target
Package qm :: Package test :: Package classes :: Module process_target
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.process_target

  1  ######################################################################## 
  2  # 
  3  # File:   process_target.py 
  4  # Author: Mark Mitchell 
  5  # Date:   07/24/2002 
  6  # 
  7  # Contents: 
  8  #   ProcessTarget 
  9  # 
 10  # Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ######################################################################## 
 17   
 18  import cPickle 
 19  import os 
 20  import qm.executable 
 21  import qm.test.cmdline 
 22  from   qm.test.target import * 
 23   
 24  ######################################################################## 
 25  # Classes 
 26  ######################################################################## 
 27   
28 -class ProcessTarget(Target):
29 """A 'ProcessTarget' runs tests in child processes.""" 30 31 arguments = [ 32 qm.fields.IntegerField( 33 name="processes", 34 title="Number of Processes", 35 description="""The number of processes to devote to running tests. 36 37 A positive integer that indicates the number of processes to 38 use when running tests. Larger numbers will allow more 39 tests to be run at once. You can experiment with this 40 value to find the number that results in the fastest 41 execution.""", 42 default_value=1), 43 qm.fields.TextField( 44 name="database_path", 45 title="Database Path", 46 description="""The path to the test database. 47 48 A string giving the directory containing the test 49 database. If this value is the empty string, QMTest uses 50 the path provided on the command line.""", 51 default_value=""), 52 qm.fields.TextField( 53 name="qmtest", 54 title="QMTest Path", 55 description="""The path to the QMTest executable. 56 57 A string giving the file name of the 'qmtest' executable 58 program. This path is used to invoke QMTest.""", 59 default_value=""), 60 ] 61
62 - class QMTestExecutable(qm.executable.Executable):
63 """A 'QMTestExecutable' redirects commands to a child process.""" 64
65 - def _InitializeParent(self):
66 67 self.command_pipe = os.pipe() 68 self.response_pipe = os.pipe()
69 70
71 - def _InitializeChild(self):
72 73 # Close the write end of the command pipe. 74 os.close(self.command_pipe[1]) 75 # And the read end of the response pipe. 76 os.close(self.response_pipe[0]) 77 # Connect the pipes to the standard input and standard 78 # output for the child. 79 os.dup2(self.command_pipe[0], sys.stdin.fileno()) 80 os.dup2(self.response_pipe[1], sys.stdout.fileno())
81 82 83
84 - def __init__(self, database, properties):
85 """Construct a new 'ProcessTarget'. 86 87 'database' -- The 'Database' containing the tests that will be 88 run. 89 90 'properties' -- A dictionary mapping strings (property names) 91 to strings (property values).""" 92 93 # Initialize the base class. 94 Target.__init__(self, database, properties)
95 96
97 - def IsIdle(self):
98 """Return true if the target is idle. 99 100 returns -- True if the target is idle. If the target is idle, 101 additional tasks may be assigned to it.""" 102 103 return self.__idle_children
104 105
106 - def Start(self, response_queue, engine=None):
107 """Start the target. 108 109 'response_queue' -- The 'Queue' in which the results of test 110 executions are placed. 111 112 'engine' -- The 'ExecutionEngine' that is starting the target, 113 or 'None' if this target is being started without an 114 'ExecutionEngine'.""" 115 116 Target.Start(self, response_queue, engine) 117 118 # There are no children yet. 119 self.__children = [] 120 self.__idle_children = [] 121 self.__busy_children = [] 122 self.__children_by_fd = {} 123 124 # Determine the test database path to use. 125 database_path = self.database_path 126 if not database_path: 127 database_path = self.GetDatabase().GetPath() 128 # See if the path to the QMTest binary was set in the 129 # target configuration. 130 qmtest_path = self.qmtest 131 if not qmtest_path: 132 # If not, fall back to the value determined when 133 # QMTest was invoked. 134 qmtest_path \ 135 = qm.test.cmdline.get_qmtest().GetExecutablePath() 136 # If there is no such value, use a default value. 137 if not qmtest_path: 138 qmtest_path = "/usr/local/bin/qmtest" 139 # Construct the command we want to invoke. 140 arg_list = (self._GetInterpreter() + 141 [ qmtest_path, '-D', database_path, "remote" ]) 142 143 # Create the subprocesses. 144 for x in xrange(self.processes): 145 # Create two pipes: one to write commands to the remote 146 # QMTest, and one to read responses. 147 e = ProcessTarget.QMTestExecutable() 148 child_pid = e.Spawn(arg_list) 149 150 # Close the read end of the command pipe. 151 os.close(e.command_pipe[0]) 152 # And the write end of the response pipe. 153 os.close(e.response_pipe[1]) 154 155 # Remember the child. 156 child = (child_pid, 157 os.fdopen(e.response_pipe[0], "r"), 158 os.fdopen(e.command_pipe[1], "w", 0)) 159 self.__children.append(child) 160 self.__idle_children.append(child) 161 self.__children_by_fd[e.response_pipe[0]] = child 162 engine.AddInputHandler(e.response_pipe[0], self.__ReadResults)
163 164
165 - def Stop(self):
166 """Stop the target. 167 168 postconditions -- The target may no longer be used.""" 169 170 # Stop the children. 171 for child in self.__children: 172 try: 173 cPickle.dump("Stop", child[2]) 174 child[2].close() 175 except: 176 pass 177 # Read any remaining results. 178 while self.__busy_children: 179 self.__ReadResults(self.__busy_children[0][1].fileno()) 180 # Wait for the children to terminate. 181 while self.__children: 182 child = self.__children.pop() 183 os.waitpid(child[0], 0) 184 185 Target.Stop(self)
186 187
188 - def RunTest(self, descriptor, context):
189 """Run the test given by 'test_id'. 190 191 'descriptor' -- The 'TestDescriptor' for the test. 192 193 'context' -- The 'Context' in which to run the test.""" 194 195 # Use the child process at the head of the list. 196 child = self.__idle_children.pop(0) 197 self.__busy_children.append(child) 198 # Write the test to the file. 199 try: 200 cPickle.dump(("RunTest", descriptor.GetId(), context), 201 child[2]) 202 except: 203 # We could not write to the child. (One situation in 204 # which this happens is that the child process has been 205 # killed.) 206 result = Result(Result.TEST, descriptor.GetId()) 207 result.NoteException() 208 self._RecordResult(result) 209 self.__idle_children.append(child)
210 211
212 - def _GetInterpreter(self):
213 """Return the interpreter to use. 214 215 returns -- A list giving the path to an interpreter, and 216 arguments to provide the interpreter. This interpreter is 217 used to run QMTest. If '[]' is returned, then no intepreter 218 is used.""" 219 220 return []
221 222
223 - def __ReadResults(self, fd):
224 """Read results from one of the children. 225 226 'fd' -- The descriptor from which the results should be read.""" 227 228 child = self.__children_by_fd[fd] 229 try: 230 results = cPickle.load(child[1]) 231 idle = None 232 for result in results: 233 self._RecordResult(result) 234 if not idle and result.GetKind() == Result.TEST: 235 self.__idle_children.append(child) 236 self.__busy_children.remove(child) 237 idle = 1 238 except EOFError: 239 self.__idle_children.append(child) 240 if child in self.__busy_children: 241 self.__busy_children.remove(child)
242

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database.ParameterDatabase-class.html0000664000076400007640000015455511122067150032541 0ustar stefanstefan qm.test.parameter_database.ParameterDatabase
Package qm :: Package test :: Module parameter_database :: Class ParameterDatabase
[hide private]
[frames] | no frames]

Class ParameterDatabase

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
      database.Database --+
                          |
                         ParameterDatabase

A database that parametrizes another database. 'Parameter' in this context refers to any name that is used as a label, and which stands for a specific set of arguments passed to tests.

The 'ParameterDatabase' class is abstract. Subclasses need to implement the '_GetParametersForTest' as well as the '_GetArgumentsForParameter' method.

Nested Classes [hide private]
  ImplicitSuite
ImplicitSuite represents a suite obtained from a test and a set of parameters applied to it.
  WrapperSuite
As tests from the wrapped Database are mapped to suites, suites from the wrapped Database have to be recreated with all tests replaced by ImplicitSuite instances.
  ParameterSuite
ParameterSuite represents a suite obtained from applying a given parameter to a suite from the wrapped DB.

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, path, arguments)
Construct a 'Database'.
source code
 
GetWrappedDatabase(self) source code
 
_GetParametersForTest(self, test_id)
Return a list of parameters that can be applied to the test 'test_id'.
source code
 
_GetArgumentsForParameter(self, test_id, parameter)
Return the set of arguments for this parameter.
source code
 
GetTest(self, test_id)
Return the 'TestDescriptor' for the test named 'test_id'.
source code
 
HasTest(self, test_id)
Check whether or not the database has a test named 'test_id'.
source code
 
GetTestIds(self, directory='', scan_subdirs=1)
Return all test IDs that begin with 'directory'.
source code
 
GetSuite(self, suite_id)
Return the 'Suite' for the suite named 'suite_id'.
source code
 
HasSuite(self, suite_id)
Check whether or not the database has a suite named 'suite_id'.
source code
 
GetSuiteIds(self, directory='', scan_subdirs=1)
Return all suite IDs that begin with 'directory'.
source code
 
GetResource(self, resource_id)
Return the 'ResourceDescriptor' for the resource 'resouce_id'.
source code
 
HasResource(self, resource_id)
Check whether or not the database has a resource named 'resource_id'.
source code
 
GetResourceIds(self, directory='', scan_subdirs=1)
Return all resource IDs that begin with 'directory'.
source code
 
GetIds(self, kind, directory='', scan_subdirs=1)
Return all IDs of the indicated 'kind' that begin with 'directory'.
source code
 
GetSubdirectories(self, directory)
Return the immediate subdirectories of 'directory'.
source code
 
GetAttachmentStore(self)
Returns the 'AttachmentStore' associated with the database.
source code
 
GetClassPath(self) source code
 
GetTestClassNames(self)
Return the kinds of tests that the database can store.
source code
 
GetResourceClassNames(self)
Return the kinds of resources that the database can store.
source code

Inherited from database.Database: ExpandIds, GetClassPaths, GetConfigurationDirectory, GetExtension, GetExtensions, GetItem, GetLabelComponents, GetPath, IsModifiable, IsValidLabel, JoinLabels, RemoveExtension, SplitLabel, SplitLabelLeft, WriteExtension

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  _argument_list = [<<class 'qm.fields.TextField'> label_class>,...
A list of all the 'Field's in this class.

Inherited from database.Database: ITEM_KINDS, RESOURCE, SUITE, TEST, arguments, kind, label_class, modifiable

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, path, arguments)
(Constructor)

source code 

Construct a 'Database'.

'path' -- A string containing the absolute path to the directory containing the database.

'arguments' -- A dictionary mapping attribute names to values. The use of this parameter is deprecated. Use keyword arguments instead.

Derived classes must call this method from their own '__init__' methods. Every derived class must have an '__init__' method that takes the path to the directory containing the database as its only argument. The path provided to the derived class '__init__' function will always be an absolute path.

Overrides: object.__init__
(inherited documentation)

_GetArgumentsForParameter(self, test_id, parameter)

source code 

Return the set of arguments for this parameter.

'test_id' -- The test id to which the parameter belongs.

'parameter' -- The parameter for which the arguments are queried.

returns -- A dictionary containing the argument as name/value pairs.

GetTest(self, test_id)

source code 

Return the 'TestDescriptor' for the test named 'test_id'.

'test_id' -- A label naming the test.

returns -- A 'TestDescriptor' corresponding to 'test_id'.

raises -- 'NoSuchTestError' if there is no test in the database named 'test_id'.

Overrides: database.Database.GetTest
(inherited documentation)

HasTest(self, test_id)

source code 

Check whether or not the database has a test named 'test_id'.

'test_id' -- A label naming the test.

returns -- True if and only if the database contains a test named 'test_id'. If this function returns true, 'GetTest' will usually succeed. However, they may be circumstances where 'HasTest' returns true and 'GetTest' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasTest' is called and the time that 'GetTest' is called.

Derived classes may override this method.

Overrides: database.Database.HasTest
(inherited documentation)

GetTestIds(self, directory='', scan_subdirs=1)

source code 

Return all test IDs that begin with 'directory'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

'returns' -- A list of all tests located within 'directory', as absolute labels.

Overrides: database.Database.GetTestIds
(inherited documentation)

GetSuite(self, suite_id)

source code 

Return the 'Suite' for the suite named 'suite_id'.

'suite_id' -- A label naming the suite.

returns -- An instance of 'Suite' (or a derived class of 'Suite') corresponding to 'suite_id'.

raises -- 'NoSuchSuiteError' if there is no test in the database named 'test_id'.

All databases must have an implicit suite called '' that contains all tests in the database. More generally, for each directory in the database, there must be a corresponding suite that contains all tests in that directory and its subdirectories.

Overrides: database.Database.GetSuite
(inherited documentation)

HasSuite(self, suite_id)

source code 

Check whether or not the database has a suite named 'suite_id'.

'suite_id' -- A label naming the suite.

returns -- True if and only if the database contains a suite named 'suite_id'. If this function returns true, 'GetSuite' will usually succeed. However, they may be circumstances where 'HasSuite' returns true and 'GetSuite' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasSuite' is called and the time that 'GetSuite' is called.

All databases must have an implicit suite called "" that contains all tests in the database. More generally, for each directory in the database, there must be a corresponding suite that contains all tests in that directory and its subdirectories.

Derived classes may override this method.

Overrides: database.Database.HasSuite
(inherited documentation)

GetSuiteIds(self, directory='', scan_subdirs=1)

source code 

Return all suite IDs that begin with 'directory'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

'returns' -- A list of all suites located within 'directory', as absolute labels.

Overrides: database.Database.GetSuiteIds
(inherited documentation)

GetResource(self, resource_id)

source code 

Return the 'ResourceDescriptor' for the resource 'resouce_id'.

'resource_id' -- A label naming the resource.

returns -- A 'ResourceDescriptor' corresponding to 'resource_id'.

raises -- 'NoSuchResourceError' if there is no resource in the database named 'resource_id'.

Overrides: database.Database.GetResource
(inherited documentation)

HasResource(self, resource_id)

source code 

Check whether or not the database has a resource named 'resource_id'.

'resource_id' -- A label naming the resource.

returns -- True if and only if the database contains a resource named 'resource_id'. If this function returns true, 'GetResource' will usually succeed. However, they may be circumstances where 'HasResource' returns true and 'GetResource' does not succeed. For example, someone might remove a critical file from the database between the time that 'HasResource' is called and the time that 'GetResource' is called.

Derived classes may override this method.

Overrides: database.Database.HasResource
(inherited documentation)

GetResourceIds(self, directory='', scan_subdirs=1)

source code 

Return all resource IDs that begin with 'directory'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

'returns' -- A list of all resources located within 'directory', as absolute labels.

Overrides: database.Database.GetResourceIds
(inherited documentation)

GetIds(self, kind, directory='', scan_subdirs=1)

source code 

Return all IDs of the indicated 'kind' that begin with 'directory'.

'kind' -- One of the 'ITEM_KINDS'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

returns -- A list of all items of the indicated 'kind' located within 'directory', as absolute labels.

Derived classes may override this method.

Overrides: database.Database.GetIds
(inherited documentation)

GetSubdirectories(self, directory)

source code 

Return the immediate subdirectories of 'directory'.

'directory' -- A label indicating a directory in the database.

returns -- A sequence of (relative) labels indictating the immediate subdirectories of 'directory'. For example, if "a.b" and "a.c" are directories in the database, this method will return "b" and "c" given "a" as 'directory'.

Derived classes may override this method.

Overrides: database.Database.GetSubdirectories
(inherited documentation)

GetAttachmentStore(self)

source code 

Returns the 'AttachmentStore' associated with the database.

returns -- The 'AttachmentStore' containing the attachments associated with tests and resources in this database.

Derived classes may override this method.

Overrides: database.Database.GetAttachmentStore
(inherited documentation)

GetTestClassNames(self)

source code 

Return the kinds of tests that the database can store.

returns -- A sequence of strings. Each string names a class, including the containing module. Only classes of these types can be stored in the database.

Derived classes may override this method. The default implementation allows all available test classes, but the derived class may allow only a subset.

Overrides: database.Database.GetTestClassNames
(inherited documentation)

GetResourceClassNames(self)

source code 

Return the kinds of resources that the database can store.

returns -- A sequence of strings. Each string names a class, including the containing module. Only resources of these types can be stored in the database.

Derived classes may override this method. The default implementation allows all available resource classes, but the derived class may allow only a subset.

Overrides: database.Database.GetResourceClassNames
(inherited documentation)

Class Variable Details [hide private]

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.TextField'> label_class>,
 <<class 'qm.fields.BooleanField'> modifiable>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.distribution-pysrc.html0000664000076400007640000012001511122067154026113 0ustar stefanstefan qm.dist.distribution
Package qm :: Package dist :: Module distribution
[hide private]
[frames] | no frames]

Source Code for Module qm.dist.distribution

 1  ######################################################################## 
 2  # 
 3  # File:   setup.py 
 4  # Author: Stefan Seefeld 
 5  # Date:   2005-11-16 
 6  # 
 7  # Contents: 
 8  #   Distribution class adding 'install_extensions' command. 
 9  # 
10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from distutils import dist 
21  from qm.dist.command.build_extensions import build_extensions 
22  from qm.dist.command.install_extensions import install_extensions 
23   
24 -class Distribution(dist.Distribution):
25 26
27 - def __init__(self, attrs=None):
28 29 # Set up the Distribution class to make it aware of the additional 30 # commands. First we need to add an attribute so setup() can pass 31 # a 'qmtest_extensions' parameter. 32 self.qmtest_extensions = None 33 dist.Distribution.__init__(self, attrs) 34 # Now add our own commands to the list. 35 self.cmdclass['build_extensions'] = build_extensions 36 self.cmdclass['install_extensions'] = install_extensions 37 38 # Register the command as a sub-command of 'install' 39 def has_extensions(cmd): return self.qmtest_extensions 40 build = self.get_command_class('build') 41 build.sub_commands.append(('build_extensions', has_extensions)) 42 install = self.get_command_class('install') 43 install.sub_commands.append(('install_extensions', has_extensions))
44

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command_host.CommandHost-class.html0000664000076400007640000004263311122067147031712 0ustar stefanstefan qm.test.classes.command_host.CommandHost
Package qm :: Package test :: Package classes :: Module command_host :: Class CommandHost
[hide private]
[frames] | no frames]

Class CommandHost

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
              host.Host --+    
                          |    
       local_host.LocalHost --+
                              |
                             CommandHost

A CommandHost runs an executable through a command.

The 'command' parameter specifies the command to use, while 'command_args' contains a set of arguments to be passed to the command.

Nested Classes [hide private]

Inherited from host.Host: Executable

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, path, arguments, environment=None, timeout=-1, relative=False)
Run a program on the remote host.
source code

Inherited from local_host.LocalHost: DeleteFile, DownloadFile, UploadAndRun, UploadFile

Inherited from local_host.LocalHost (private): _SameFile

Inherited from host.Host: __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  command = TextField(description= "Name of the command" " used ...
  command_args = SetField(TextField(description= "Set of argumen...

Inherited from host.Host: kind

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, path, arguments, environment=None, timeout=-1, relative=False)

source code 

Run a program on the remote host.

'path' -- The name of the program to run, on the remote host. If 'relative' is true, or if 'path' is not an absolute path but does contain at least one directory separator, then 'path' is interpreted relative to the default directory. Otherwise, 'path' is used unmodified.

'arguments' -- The sequence of arguments that should be passed to the program.

'environment' -- If not 'None', a dictionary of pairs of strings to add to the environment of the running program.

'timeout' -- The number of seconds the program is permitted to execute. After the 'timeout' expires, the program will be terminated. However, in some cases (such as when using 'rsh') it will be the local side of the connection that is closed. The remote side of the connection may or may not continue to operate, depending on the vagaries of the remote operating system.

returns -- A pair '(status, output)'. The 'status' is the exit status returned by the program, or 'None' if the exit status is not available. The 'output' is a string giving the combined standard output and standard error output from the program.

Overrides: host.Host.Run
(inherited documentation)

Class Variable Details [hide private]

command

Value:
TextField(description= "Name of the command" " used to run the executa\
ble.")

command_args

Value:
SetField(TextField(description= "Set of arguments" " passed to the com\
mand."))

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Let-pysrc.html0000664000076400007640000016420011122067156030645 0ustar stefanstefan qm.external.DocumentTemplate.DT_Let
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Let
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_Let

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13   
 14  ''' The Let tag was contributed to Zope by and is copyright, 1999 
 15      Phillip J. Eby.  Permission has been granted to release the Let tag 
 16      under the Zope Public License. 
 17   
 18   
 19     Let name=value... 
 20   
 21     The 'let' tag is used to bind variables to values within a block. 
 22   
 23     The text enclosed in the let tag is rendered using information 
 24     from the given variables or expressions. 
 25   
 26     For example:: 
 27   
 28       <!--#let foofunc="foo()" my_bar=bar--> 
 29         foo() = <!--#var foofunc-->, 
 30         bar = <!--#var my_bar--> 
 31       <!--#/let--> 
 32   
 33     Notice that both 'name' and 'expr' style attributes may be used to 
 34     specify data.  'name' style attributes (e.g. my_bar=bar) will be 
 35     rendered as they are for var/with/in/etc.  Quoted attributes will 
 36     be treated as Python expressions. 
 37   
 38     Variables are processed in sequence, so later assignments can 
 39     reference and/or overwrite the results of previous assignments, 
 40     as desired. 
 41  ''' 
 42   
 43  from DT_Util import render_blocks, Eval, ParseError 
 44  from DT_Util import str # Probably needed due to hysterical pickles. 
 45  import re 
 46   
 47   
48 -class Let:
49 blockContinuations=() 50 name='let' 51
52 - def __init__(self, blocks):
53 tname, args, section = blocks[0] 54 self.__name__ = args 55 self.section = section.blocks 56 self.args = args = parse_let_params(args) 57 58 for i in range(len(args)): 59 name,expr = args[i] 60 if expr[:1]=='"' and expr[-1:]=='"' and len(expr) > 1: 61 # expr shorthand 62 expr=expr[1:-1] 63 try: args[i] = name, Eval(expr).eval 64 except SyntaxError, v: 65 m,(huh,l,c,src) = v 66 raise ParseError, ( 67 '<strong>Expression (Python) Syntax error</strong>:' 68 '\n<pre>\n%s\n</pre>\n' % v[0], 69 'let')
70 - def render(self, md):
71 d={}; md._push(d) 72 try: 73 for name,expr in self.args: 74 if type(expr) is type(''): d[name]=md[expr] 75 else: d[name]=expr(md) 76 return render_blocks(self.section, md) 77 finally: md._pop(1)
78 79 __call__ = render
80 81
82 -def parse_let_params(text, 83 result=None, 84 tag='let', 85 parmre=re.compile('([\000- ]*([^\000- ="]+)=([^\000- ="]+))'), 86 qparmre=re.compile('([\000- ]*([^\000- ="]+)="([^"]*)")'), 87 **parms):
88 89 result=result or [] 90 91 mo = parmre.match(text) 92 mo1= qparmre.match(text) 93 94 if mo is not None: 95 name=mo.group(2) 96 value=mo.group(3) 97 l=len(mo.group(1)) 98 elif mo1 is not None: 99 name=mo1.group(2) 100 value='"%s"' % mo1.group(3) 101 l=len(mo1.group(1)) 102 else: 103 if not text or not text.strip(): return result 104 raise ParseError, ('invalid parameter: "%s"' % text, tag) 105 106 result.append((name,value)) 107 108 text=text[l:].strip() 109 if text: return parse_let_params(text,result,tag,**parms) 110 else: return result
111

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_base.DejaGNUBase-class.html0000664000076400007640000002604511122067147031441 0ustar stefanstefan qm.test.classes.dejagnu_base.DejaGNUBase
Package qm :: Package test :: Package classes :: Module dejagnu_base :: Class DejaGNUBase
[hide private]
[frames] | no frames]

Class DejaGNUBase

source code

A 'DejaGNUBase' is a base class for tests and resources.

Instance Methods [hide private]
 
_RecordCommand(self, result, command)
Record the execution of 'command'.
source code
 
_RecordCommandOutput(self, result, index, status, output)
Record the result of running a command.
source code
 
_SetUp(self, context)
Prepare to run a test.
source code
Method Details [hide private]

_RecordCommand(self, result, command)

source code 

Record the execution of 'command'.

'result' -- The 'Result' for the test.

'command' -- A sequence of strings, giving the arguments to a command that is about to be executed.

returns -- An integer giving the the index for this command. This value should be provided to '_RecordCommandOutput' after the command's output is known.

_RecordCommandOutput(self, result, index, status, output)

source code 

Record the result of running a command.

'result' -- The 'Result' for the test.

'index' -- An integer, return from a previous call to '_RecordCommand'.

'status' -- The exit status from the command.

'output' -- A string containing the output, if any, from the command.

_SetUp(self, context)

source code 

Prepare to run a test.

'context' -- The 'Context' in which this test will run.

This method may be overridden by derived classes, but they must call this version.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.distribution-module.html0000664000076400007640000001102711122067145026242 0ustar stefanstefan qm.dist.distribution
Package qm :: Package dist :: Module distribution
[hide private]
[frames] | no frames]

Module distribution

source code

Classes [hide private]
  Distribution
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test_run.TestRun-class.html0000664000076400007640000004711411122067151026630 0ustar stefanstefan qm.test.test_run.TestRun
Package qm :: Package test :: Module test_run :: Class TestRun
[hide private]
[frames] | no frames]

Class TestRun

source code

object --+
         |
        TestRun
Known Subclasses:

A 'TestRun' stores the 'Result's from a single test run.

The primary contents of a 'TestRun' are the the 'Result's of the run. In addition, each 'TestRun' has an associated set of annotations, which are used to store global information about the 'TestRun'.

Instance Methods [hide private]
 
GetResult(self, id, kind='test')
Return the 'Result' for the indicated test.
source code
 
GetAnnotation(self, key)
Return the annotation associated with 'key'.
source code
 
GetAnnotations(self)
Return this run's dictionary of annotations.
source code
 
GetAllResults(self, directory='', kind='test')
Return 'Result's from the given directory..
source code
 
GetResultsByOutcome(self, outcome=None, directory='', kind='test')
Return 'Result's with a particular outcome.
source code
 
CountOutcomes(self, directory='', outcome=None)
Return statistics about the outcomes of tests.
source code

Inherited from object: __delattr__, __getattribute__, __hash__, __init__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

GetResult(self, id, kind='test')

source code 

Return the 'Result' for the indicated test.

'id' -- The name of a test or resource.

'kind' -- The kind of result to retrieve. See 'Result' for a list of the available result kinds.

returns -- The 'Result' corresponding to 'test_id'.

raises -- 'KeyError' if there is no result of the given 'kind' for 'id' in the test run.

GetAnnotation(self, key)

source code 

Return the annotation associated with 'key'.

'key' -- A string giving the name of an annotation.

returns -- A string giving the value of the annotation, or 'None' if there is no such annotation.

GetAnnotations(self)

source code 

Return this run's dictionary of annotations.

returns -- A dictionary mapping annotation names (strings) to values (also strings).

GetAllResults(self, directory='', kind='test')

source code 

Return 'Result's from the given directory..

'directory' -- A path to a directory in the test database.

'kind' -- The kind of results to return.

returns -- All the results within 'directory' (including its subdirectories).

GetResultsByOutcome(self, outcome=None, directory='', kind='test')

source code 

Return 'Result's with a particular outcome.

'outcome' -- One of the 'Result.outcomes', or 'None'.

'directory' -- A path to a directory in the test database.

'kind' -- The kind of results to return.

returns -- All the results within 'directory' (including its subdirectories) that have the indicated 'outcome', or, if 'outcome' is 'None', all test results from 'directory'.

CountOutcomes(self, directory='', outcome=None)

source code 

Return statistics about the outcomes of tests.

'directory' -- A path to a directory in the test database.

'outcome' -- If not 'None', one of the 'Result.outcomes'.

returns -- A dictionary mapping outcomes to the number of test results with that outcome located within 'directory' and its subdirectories. If 'outcome' is not 'None', the dictionary will have an entry only for the 'outcome' specified.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler_test.CompilerTest-class.html0000664000076400007640000011652411122067147032307 0ustar stefanstefan qm.test.classes.compiler_test.CompilerTest
Package qm :: Package test :: Package classes :: Module compiler_test :: Class CompilerTest
[hide private]
[frames] | no frames]

Class CompilerTest

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
                  test.Test --+
                              |
               CompilerBase --+
                              |
                             CompilerTest

A 'CompilerTest' tests a compiler.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code
 
_GetCompiler(self, context)
Return the 'Compiler' to use.
source code
 
_GetCompilationSteps(self, context)
Return the compilation steps for this test.
source code
 
_GetTarget(self, context)
Returns a target for the executable to be run on.
source code
 
_IsExecutionRequired(self)
Returns true if the generated executable should be run.
source code
 
_GetExecutableArguments(self)
Returns the arguments to the generated executable.
source code
 
_MustExecutableExitSuccessfully(self)
Returns true if the executable must exit with code zero.
source code
 
_GetAnnotationPrefix(self)
Return the prefix to use for result annotations.
source code
 
_GetLibraryDirectories(self, context)
Returns the directories to search for libraries.
source code
 
_RunExecutable(self, path, context, result)
Run an executable generated by the compiler.
source code
 
_CheckOutput(self, context, result, prefix, output, diagnostics)
Check that the 'output' contains appropriate diagnostics.
source code
 
_CheckExecutableOutput(self, result, output)
Checks the output from the generated executable.
source code
 
_IsDiagnosticExpected(self, emitted, expected)
Returns true if 'emitted' matches 'expected'.
source code
 
_DiagnosticsToString(self, result, annotation, diagnostics)
Return a string representing the 'diagnostics'.
source code

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  _ignored_diagnostic_regexps = ()
A sequence of regular expressions matching diagnostics to ignore.

Inherited from test.Test: PREREQUISITES_FIELD_ID, arguments, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

Overrides: test.Test.Run

_GetCompiler(self, context)

source code 

Return the 'Compiler' to use.

'context' -- The 'Context' in which this test is being executed.

_GetCompilationSteps(self, context)

source code 

Return the compilation steps for this test.

'context' -- The 'Context' in which this test is being executed.

returns -- A sequence of 'CompilationStep' objects.

_GetTarget(self, context)

source code 

Returns a target for the executable to be run on.

'context' -- The Context in which this test is being executed.

returns -- A Host to run the executable on.

_IsExecutionRequired(self)

source code 

Returns true if the generated executable should be run.

returns -- True if the generated executable should be run.

_GetExecutableArguments(self)

source code 

Returns the arguments to the generated executable.

returns -- A list of strings, to be passed as argumensts to the generated executable.

_MustExecutableExitSuccessfully(self)

source code 

Returns true if the executable must exit with code zero.

returns -- True if the generated executable (if any) must exit with code zero. Note that the executable will not be run at all (and so the return value of this function will be ignored) if '_IsExecutionRequired' does not return true.

_GetAnnotationPrefix(self)

source code 

Return the prefix to use for result annotations.

returns -- The prefix to use for result annotations.

_GetLibraryDirectories(self, context)

source code 

Returns the directories to search for libraries.

'context' -- A 'Context' giving run-time parameters to the test.

returns -- A sequence of strings giving the paths to the directories to search for libraries.

_RunExecutable(self, path, context, result)

source code 

Run an executable generated by the compiler.

'path' -- The path to the generated executable.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

_CheckOutput(self, context, result, prefix, output, diagnostics)

source code 

Check that the 'output' contains appropriate diagnostics.

'context' -- The 'Context' for the test that is being executed.

'result' -- The 'Result' of the test.

'prefix' -- A string giving the prefix for any annotations to be added to the 'result'.

'output' -- A string giving the output of the compiler.

'diagnostics' -- The diagnostics that are expected for the compilation.

returns -- True if there were no errors so severe as to prevent execution of the test.

_CheckExecutableOutput(self, result, output)

source code 

Checks the output from the generated executable.

'result' -- The 'Result' object for this test.

'output' -- The output generated by the executable.

If the output is unsatisfactory, 'result' is modified appropriately.

_IsDiagnosticExpected(self, emitted, expected)

source code 

Returns true if 'emitted' matches 'expected'.

'emitted' -- A 'Diagnostic emitted by the compiler.

'expected' -- A 'Diagnostic' indicating an expectation about a diagnostic to be emitted by the compiler.

returns -- True if the 'emitted' was expected by the 'expected'.

_DiagnosticsToString(self, result, annotation, diagnostics)

source code 

Return a string representing the 'diagnostics'.

'diagnostics' -- A sequence of 'Diagnostic' instances.

returns -- A string representing the 'Diagnostic's, with one diagnostic message per line.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.reader_test_run-pysrc.html0000664000076400007640000007606211122067154026611 0ustar stefanstefan qm.test.reader_test_run
Package qm :: Package test :: Module reader_test_run
[hide private]
[frames] | no frames]

Source Code for Module qm.test.reader_test_run

 1  ######################################################################## 
 2  # 
 3  # File:   reader_test_run.py 
 4  # Author: Mark Mitchell 
 5  # Date:   2005-08-08 
 6  # 
 7  # Contents: 
 8  #   QMTest ReaderTestRun class. 
 9  # 
10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from qm.test.result import Result 
21  from qm.test.test_run import TestRun 
22  from qm.test.result_reader import ResultReader 
23   
24  ######################################################################## 
25  # Classes 
26  ######################################################################## 
27   
28 -class ReaderTestRun(TestRun):
29 """A 'ReaderTestRun' reads its results using a 'ResultReader'. 30 31 A 'ResultReader' provides an iterative interface for reading 32 results. A 'ReaderTestRun' uses a 'ResultReader' to populate a 33 dictionary storing all the results from the reader.""" 34
35 - def __init__(self, reader):
36 """Create a new 'ReaderTestRun' 37 38 'reader' -- The 'ResultReader' from which we are to read 39 results.""" 40 41 # Read the results. 42 self.__results = {} 43 for kind in Result.kinds: 44 self.__results[kind] = {} 45 for result in reader: 46 self.__results[result.GetKind()][result.GetId()] = result 47 48 # Read the annotations. 49 self.__annotations = reader.GetAnnotations()
50 51
52 - def GetResult(self, id, kind = Result.TEST):
53 54 return self.__results[kind].get(id)
55 56
57 - def GetAnnotation(self, key):
58 59 return self.__annotations.get(key)
60 61
62 - def GetAnnotations(self):
63 64 return self.__annotations
65 66
67 - def GetAllResults(self, directory = "", kind = Result.TEST):
68 69 if directory == "": 70 return self.__results[kind].values() 71 else: 72 return [self.__results[kind][id] for id in self.__results[kind] 73 if id.startswith(directory)]
74

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_In.InClass-class.html0000664000076400007640000002620611122067146031771 0ustar stefanstefan qm.external.DocumentTemplate.DT_In.InClass
Package qm :: Package external :: Package DocumentTemplate :: Module DT_In :: Class InClass
[hide private]
[frames] | no frames]

Class InClass

source code

Instance Methods [hide private]
 
__init__(self, blocks) source code
 
renderwb(self, md) source code
 
renderwob(self, md)
RENDER WithOutBatch
source code
 
sort_sequence(self, sequence) source code
 
reverse_sequence(self, sequence) source code
Class Variables [hide private]
  elses = None
  mapping = None
  batch = None
  sort = None
  expr = None
  start_name_re = None
  reverse = None
  reverse_expr = None
  sort_expr = None
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.Field-class.html0000664000076400007640000012706311122067146024702 0ustar stefanstefan qm.fields.Field
qm :: fields :: Field :: Class Field
[hide private]
[frames] | no frames]

Class Field

source code

object --+
         |
        Field
Known Subclasses:

A 'Field' is a named, typed component of a data structure.

Instance Methods [hide private]
 
__init__(self, name='', default_value=None, title='', description='', hidden='false', read_only='false', computed='false')
Create a new (generic) field.
source code
 
SetName(self, name)
Set the name of the field.
source code
 
GetName(self)
Return the name of the field.
source code
 
GetDefaultValue(self)
Return the default value for this field.
source code
 
GetTitle(self)
Return the user-friendly title of the field.
source code
 
GetDescription(self)
Return a description of this field.
source code
 
GetBriefDescription(self)
Return a brief description of this field.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
GetHtmlHelp(self, edit=0)
Generate help text about this field in HTML format.
source code
 
GetSubfields(self)
Returns the sequence of subfields contained in this field.
source code
 
IsComputed(self)
Returns true if this field is computed automatically.
source code
 
IsHidden(self)
Returns true if this 'Field' should be hidden from users.
source code
 
IsReadOnly(self)
Returns true if this 'Field' cannot be modified by users.
source code
 
FormatValueAsText(self, value, columns=72)
Return a plain text rendering of a 'value' for this field.
source code
 
FormatValueAsHtml(self, server, value, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
MakeDomNodeForValue(self, value, document)
Generate a DOM element node for a value of this field.
source code
 
Validate(self, value)
Validate a field value.
source code
 
ParseTextValue(self, value)
Parse a value represented as a string.
source code
 
ParseFormValue(self, request, name, attachment_stores)
Convert a value submitted from an HTML form.
source code
 
GetValueFromDomNode(self, node, attachment_store)
Return a value for this field represented by DOM 'node'.
source code
 
GetHtmlFormFieldName(self)
Return the form field name corresponding this field.
source code
 
__repr__(self)
repr(x)
source code

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]
  form_field_prefix = '_field_'
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', default_value=None, title='', description='', hidden='false', read_only='false', computed='false')
(Constructor)

source code 

Create a new (generic) field.

'name' -- The name of the field.

'default_value' -- The default value for this field.

'title' -- The name given this field when it is displayed in user interfaces.

'description' -- A string explaining the purpose of this field. The 'description' must be provided as structured text. The first line of the structured text must be a one-sentence description of the field; that line is extracted by 'GetBriefDescription'.

'hidden' -- If true, this field is for internal puprpose only and is not shown in user interfaces.

'read_only' -- If true, this field may not be modified by users.

'computed' -- If true, this field is computed automatically. All computed fields are implicitly hidden and implicitly read-only.

The boolean parameters (such as 'hidden') use the convention that true is represented by the string '"true"'; any other value is false. This convention is a historical artifact.

Overrides: object.__init__

GetDescription(self)

source code 

Return a description of this field.

This description is used when displaying detailed help information about the field.

GetBriefDescription(self)

source code 

Return a brief description of this field.

This description is used when prompting for input, or when displaying the current value of the field.

GetHtmlHelp(self, edit=0)

source code 

Generate help text about this field in HTML format.

'edit' -- If true, display information about editing controls for this field.

GetSubfields(self)

source code 

Returns the sequence of subfields contained in this field.

returns -- The sequence of subfields contained in this field. If there are no subfields, an empty sequence is returned.

IsComputed(self)

source code 

Returns true if this field is computed automatically.

returns -- True if this field is computed automatically. A computed field is never displayed to users and is not stored should not be stored; the class containing the field is responsible for recomputing it as necessary.

IsHidden(self)

source code 

Returns true if this 'Field' should be hidden from users.

returns -- True if this 'Field' should be hidden from users. The value of a hidden field is not displayed in the GUI.

IsReadOnly(self)

source code 

Returns true if this 'Field' cannot be modified by users.

returns -- True if this 'Field' cannot be modified by users. The GUI does not allow users to modify a read-only field.

FormatValueAsText(self, value, columns=72)

source code 

Return a plain text rendering of a 'value' for this field.

'columns' -- The maximum width of each line of text.

returns -- A plain-text string representing 'value'.

FormatValueAsHtml(self, server, value, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

MakeDomNodeForValue(self, value, document)

source code 

Generate a DOM element node for a value of this field.

'value' -- The value to represent.

'document' -- The containing DOM document node.

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

ParseTextValue(self, value)

source code 

Parse a value represented as a string.

'value' -- A string representing the value.

returns -- The corresponding field value. The value returned should be processed by 'Validate' to ensure that it is valid before it is returned.

ParseFormValue(self, request, name, attachment_stores)

source code 

Convert a value submitted from an HTML form.

'request' -- The 'WebRequest' containing a value corresponding to this field.

'name' -- The name corresponding to this field in the 'request'.

'attachment_stores' -- A dictionary mapping 'AttachmentStore' ids (in the sense of Python's 'id' built-in) to the 'AttachmentStore's themselves.

returns -- A pair '(value, redisplay)'. 'value' is the value for this field, as indicated in 'request'. 'redisplay' is true if and only if the form should be redisplayed, rather than committed. If an error occurs, an exception is thrown.

GetValueFromDomNode(self, node, attachment_store)

source code 

Return a value for this field represented by DOM 'node'.

This method does not validate the value for this particular instance; it only makes sure the node is well-formed, and returns a value of the correct Python type.

'node' -- The DOM node that is being evaluated.

'attachment_store' -- For attachments, the store that should be used.

If the 'node' is incorrectly formed, this method should raise an exception.

GetHtmlFormFieldName(self)

source code 

Return the form field name corresponding this field.

returns -- A string giving the name that should be used for this field when used in an HTML form.

__repr__(self)
(Representation operator)

source code 

repr(x)

Overrides: object.__repr__
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler.EDG-class.html0000664000076400007640000003074011122067147027230 0ustar stefanstefan qm.test.classes.compiler.EDG
Package qm :: Package test :: Package classes :: Module compiler :: Class EDG
[hide private]
[frames] | no frames]

Class EDG

source code

Compiler --+
           |
          EDG

An 'EDG' is an Edison Design Group compiler.

Instance Methods [hide private]
 
ParseOutput(self, output, ignore_regexps=())
Return the 'Diagnostic's indicated in the 'output'.
source code

Inherited from Compiler: Compile, ExecuteCommand, GetCompilationCommand, GetExecutableExtension, GetLDFlags, GetObjectExtension, GetOptions, GetPath, SetLDFlags, SetOptions, __init__

Inherited from Compiler (private): _GetModeSwitches

Class Variables [hide private]
  __diagnostic_regexp = re.compile('^"(?P<file>.*)", line (?P<li...

Inherited from Compiler: MODE_ASSEMBLE, MODE_COMPILE, MODE_LINK, MODE_PREPROCESS, modes

Method Details [hide private]

ParseOutput(self, output, ignore_regexps=())

source code 

Return the 'Diagnostic's indicated in the 'output'.

'output' -- A string giving the output from the compiler.

'ignore_regexps' -- A sequence of regular expressions. If a diagnostic message matches one of these regular expressions, it will be ignored.

returns -- A list of 'Diagnostic's corresponding to the messages indicated in 'output', in the order that they were emitted.

Overrides: Compiler.ParseOutput

Class Variable Details [hide private]

__diagnostic_regexp

Value:
re.compile('^"(?P<file>.*)", line (?P<line>.*): ' '(?P<severity>.*): (\
?P<message>.*)$')

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result-pysrc.html0000664000076400007640000035531711122067154024745 0ustar stefanstefan qm.test.result
Package qm :: Package test :: Module result
[hide private]
[frames] | no frames]

Source Code for Module qm.test.result

  1  ######################################################################## 
  2  # 
  3  # File:   result.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2001-10-10 
  6  # 
  7  # Contents: 
  8  #   QMTest Result class. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  from   qm.test.context import ContextException 
 22  import sys, os 
 23  import types 
 24  import cgi 
 25   
 26  ######################################################################## 
 27  # Classes 
 28  ######################################################################## 
 29   
30 -class Result:
31 """A 'Result' describes the outcome of a test. 32 33 A 'Result' contains two pieces of data: an outcome and a set 34 of annotations. The outcome indicates whether the test passed 35 or failed. More specifically, the outcome may be one of the 36 following constants: 37 38 'Result.PASS' -- The test passed. 39 40 'Result.FAIL' -- The test failed. 41 42 'Result.ERROR' -- Something went wrong in the process of trying to 43 execute the test. For example, if the Python code implementing 44 the 'Run' method in the test class raised an exception, the 45 outcome would be 'Result.ERROR'. 46 47 'Result.UNTESTED' -- QMTest did not even try to run the test. 48 For example, if a prerequiste was not satisfied, then this outcome 49 will be used.' 50 51 The annotations are a dictionary, mapping strings to strings. 52 53 The indices should be of the form 'class.name' where 'class' is 54 the name of the test class that created the annotation. Any 55 annotations created by QMTest, as opposed to the test class, will 56 have indices of the form 'qmtest.name'. 57 58 The annotation values are HTML. When displayed in the GUI, the 59 HTML is inserted directly into the result page; when the 60 command-line interface is used the HTML is converted to plain 61 text. 62 63 Currently, QMTest recognizes the following built-in annotations: 64 65 'Result.CAUSE' -- For results whose outcome is not 'FAIL', this 66 annotation gives a brief description of why the test failed. The 67 preferred form of this message is a phrase like "Incorrect 68 output." or "Exception thrown." The message should begin with a 69 capital letter and end with a period. Most results formatters 70 will display this information prominently. 71 72 'Result.EXCEPTION' -- If an exeption was thrown during the 73 test execution, a brief description of the exception. 74 75 'Result.TARGET' -- This annotation indicates on which target the 76 test was executed. 77 78 'Result.TRACEBACK' -- If an exeption was thrown during the test 79 execution, a representation of the traceback indicating where 80 the exception was thrown. 81 82 A 'Result' object has methods that allow it to act as a dictionary 83 from annotation names to annotation values. You can directly add 84 an annotation to a 'Result' by writing code of the form 85 'result[CAUSE] = "Exception thrown."'. 86 87 A 'Result' object is also used to describe the outcome of 88 executing either setup or cleanup phase of a 'Resource'.""" 89 90 # Constants for result kinds. 91 92 RESOURCE_SETUP = "resource_setup" 93 RESOURCE_CLEANUP = "resource_cleanup" 94 TEST = "test" 95 96 # Constants for outcomes. 97 98 FAIL = "FAIL" 99 ERROR = "ERROR" 100 UNTESTED = "UNTESTED" 101 PASS = "PASS" 102 103 # Constants for predefined annotations. 104 105 CAUSE = "qmtest.cause" 106 EXCEPTION = "qmtest.exception" 107 RESOURCE = "qmtest.resource" 108 TARGET = "qmtest.target" 109 TRACEBACK = "qmtest.traceback" 110 START_TIME = "qmtest.start_time" 111 END_TIME = "qmtest.end_time" 112 113 # Other class variables. 114 115 kinds = [ RESOURCE_SETUP, RESOURCE_CLEANUP, TEST ] 116 """A list of the possible kinds.""" 117 118 outcomes = [ ERROR, FAIL, UNTESTED, PASS ] 119 """A list of the possible outcomes. 120 121 The order of the 'outcomes' is significant; they are ordered from 122 most interesting to least interesting from the point of view of 123 someone browsing results.""" 124
125 - def __init__(self, kind, id, outcome=PASS, annotations={}):
126 """Construct a new 'Result'. 127 128 'kind' -- The kind of result. The value must be one of the 129 'Result.kinds'. 130 131 'id' -- The label for the test or resource to which this 132 result corresponds. 133 134 'outcome' -- The outcome associated with the test. The value 135 must be one of the 'Result.outcomes'. 136 137 'annotations' -- The annotations associated with the test.""" 138 139 assert kind in Result.kinds 140 assert outcome in Result.outcomes 141 142 self.__kind = kind 143 self.__id = id 144 self.__outcome = outcome 145 self.__annotations = annotations.copy()
146 147
148 - def __getstate__(self):
149 """Return a representation of this result for pickling. 150 151 By using an explicit tuple representation of 'Result's when 152 storing them in a pickle file, we decouple our storage format 153 from internal implementation details (e.g., the names of private 154 variables).""" 155 156 # A tuple containing the data needed to reconstruct a 'Result'. 157 # No part of this structure should ever be a user-defined type, 158 # because that will introduce interdependencies that we want to 159 # avoid. 160 return (self.__kind, 161 self.__id, 162 self.__outcome, 163 self.__annotations)
164 165
166 - def __setstate__(self, pickled_state):
167 """Construct a 'Result' from its pickled form.""" 168 169 if isinstance(pickled_state, dict): 170 # Old style pickle, from before we defined '__getstate__'. 171 # (Notionally, this is version "0".) The state is a 172 # dictionary containing the variables we used to have. 173 self.__kind = pickled_state["_Result__kind"] 174 self.__id = pickled_state["_Result__id"] 175 self.__outcome = pickled_state["_Result__outcome"] 176 self.__annotations = pickled_state["_Result__annotations"] 177 # Also has a key "_Result__context" containing a (probably 178 # invalid) context object, but we discard it. 179 else: 180 assert isinstance(pickled_state, tuple) \ 181 and len(pickled_state) == 4 182 # New style pickle, from after we defined '__getstate__'. 183 # (Notionally, this is version "1".) The state is a tuple 184 # containing the values of the variables we care about. 185 (self.__kind, 186 self.__id, 187 self.__outcome, 188 self.__annotations) = pickled_state
189 190
191 - def GetKind(self):
192 """Return the kind of result this is. 193 194 returns -- The kind of entity (one of the 'kinds') to which 195 this result corresponds.""" 196 197 return self.__kind
198 199
200 - def GetOutcome(self):
201 """Return the outcome associated with the test. 202 203 returns -- The outcome associated with the test. This value 204 will be one of the 'Result.outcomes'.""" 205 206 return self.__outcome
207 208
209 - def SetOutcome(self, outcome, cause = None, annotations = {}):
210 """Set the outcome associated with the test. 211 212 'outcome' -- One of the 'Result.outcomes'. 213 214 'cause' -- If not 'None', this value becomes the value of the 215 'Result.CAUSE' annotation. 216 217 'annotations' -- The annotations are added to the current set 218 of annotations.""" 219 220 assert outcome in Result.outcomes 221 self.__outcome = outcome 222 if cause: 223 self.SetCause(cause) 224 self.Annotate(annotations)
225 226
227 - def Annotate(self, annotations):
228 """Add 'annotations' to the current set of annotations.""" 229 self.__annotations.update(annotations)
230 231
232 - def Fail(self, cause = None, annotations = {}):
233 """Mark the test as failing. 234 235 'cause' -- If not 'None', this value becomes the value of the 236 'Result.CAUSE' annotation. 237 238 'annotations' -- The annotations are added to the current set 239 of annotations.""" 240 241 self.SetOutcome(Result.FAIL, cause, annotations)
242 243
244 - def GetId(self):
245 """Return the label for the test or resource. 246 247 returns -- A label indicating indicating to which test or 248 resource this result corresponds.""" 249 250 return self.__id
251 252
253 - def GetCause(self):
254 """Return the cause of failure, if the test failed. 255 256 returns -- If the test failed, return the cause of the 257 failure, if available.""" 258 259 if self.has_key(Result.CAUSE): 260 return self[Result.CAUSE] 261 else: 262 return ""
263 264
265 - def SetCause(self, cause):
266 """Set the cause of failure. 267 268 'cause' -- A string indicating the cause of failure. Like all 269 annotations, 'cause' will be interested as HTML.""" 270 271 self[Result.CAUSE] = cause
272 273
274 - def Quote(self, string):
275 """Return a version of string suitable for an annotation value. 276 277 Performs appropriate quoting for a string that should be taken 278 verbatim; this includes HTML entity escaping, and addition of 279 <pre> tags. 280 281 'string' -- The verbatim string to be quoted. 282 283 returns -- The quoted string.""" 284 285 return "<pre>%s</pre>" % cgi.escape(string)
286 287
288 - def NoteException(self, 289 exc_info = None, 290 cause = None, 291 outcome = ERROR):
292 """Note that an exception occurred during execution. 293 294 'exc_info' -- A triple, in the same form as that returned 295 from 'sys.exc_info'. If 'None', the value of 'sys.exc_info()' 296 is used instead. 297 298 'cause' -- The value of the 'Result.CAUSE' annotation. If 299 'None', a default message is used. 300 301 'outcome' -- The outcome of the test, now that the exception 302 has occurred. 303 304 A test class can call this method if an exception occurs while 305 the test is being run.""" 306 307 if not exc_info: 308 exc_info = sys.exc_info() 309 310 exception_type = exc_info[0] 311 312 # If no cause was specified, use an appropriate message. 313 if not cause: 314 if exception_type is ContextException: 315 cause = str(exc_info[1]) 316 else: 317 cause = "An exception occurred." 318 319 # For a 'ContextException', indicate which context variable 320 # was invalid. 321 if exception_type is ContextException: 322 self["qmtest.context_variable"] = exc_info[1].key 323 324 self.SetOutcome(outcome, cause) 325 self[Result.EXCEPTION] \ 326 = self.Quote("%s: %s" % exc_info[:2]) 327 self[Result.TRACEBACK] \ 328 = self.Quote(qm.format_traceback(exc_info))
329 330
331 - def CheckExitStatus(self, prefix, desc, status, non_zero_exit_ok = 0):
332 """Check the exit status from a command. 333 334 'prefix' -- The prefix that should be used when creating 335 result annotations. 336 337 'desc' -- A description of the executing program. 338 339 'status' -- The exit status, as returned by 'waitpid'. 340 341 'non_zero_exit_ok' -- True if a non-zero exit code is not 342 considered failure. 343 344 returns -- False if the test failed, true otherwise.""" 345 346 if sys.platform == "win32" or os.WIFEXITED(status): 347 # Obtain the exit code. 348 if sys.platform == "win32": 349 exit_code = status 350 else: 351 exit_code = os.WEXITSTATUS(status) 352 # If the exit code is non-zero, the test fails. 353 if exit_code != 0 and not non_zero_exit_ok: 354 self.Fail("%s failed with exit code %d." % (desc, exit_code)) 355 # Record the exit code in the result. 356 self[prefix + "exit_code"] = str(exit_code) 357 return False 358 359 elif os.WIFSIGNALED(status): 360 # Obtain the signal number. 361 signal = os.WTERMSIG(status) 362 # If the program gets a fatal signal, the test fails . 363 self.Fail("%s received fatal signal %d." % (desc, signal)) 364 self[prefix + "signal"] = str(signal) 365 return False 366 else: 367 # A process should only be able to stop by exiting, or 368 # by being terminated with a signal. 369 assert None 370 371 return True
372 373
374 - def MakeDomNode(self, document):
375 """Generate a DOM element node for this result. 376 377 Note that the context is not represented in the DOM node. 378 379 'document' -- The containing DOM document. 380 381 returns -- The element created.""" 382 383 # The node is a result element. 384 element = document.createElement("result") 385 element.setAttribute("id", self.GetId()) 386 element.setAttribute("kind", self.GetKind()) 387 element.setAttribute("outcome", str(self.GetOutcome())) 388 # Add an annotation element for each annotation. 389 keys = self.keys() 390 keys.sort() 391 for key in keys: 392 value = self[key] 393 annotation_element = document.createElement("annotation") 394 # The annotation name is an attribute. 395 annotation_element.setAttribute("name", str(key)) 396 # The annotation value is contained in a text node. The 397 # data is enclosed in quotes for robustness if the 398 # document is pretty-printed. 399 node = document.createTextNode('"' + str(value) + '"') 400 annotation_element.appendChild(node) 401 # Add the annotation element to the result node. 402 element.appendChild(annotation_element) 403 404 return element
405 406 # These methods allow 'Result' to act like a dictionary of 407 # annotations. 408
409 - def __getitem__(self, key):
410 assert type(key) in types.StringTypes 411 return self.__annotations[key]
412 413
414 - def __setitem__(self, key, value):
415 assert type(key) in types.StringTypes 416 assert type(value) in types.StringTypes 417 self.__annotations[key] = value
418 419
420 - def __delitem__(self, key):
421 assert type(key) in types.StringTypes 422 del self.__annotations[key]
423 424
425 - def get(self, key, default=None):
426 assert type(key) in types.StringTypes 427 return self.__annotations.get(key, default)
428 429
430 - def has_key(self, key):
431 assert type(key) in types.StringTypes 432 return self.__annotations.has_key(key)
433 434
435 - def keys(self):
436 return self.__annotations.keys()
437 438
439 - def items(self):
440 return self.__annotations.items()
441 442 443 ######################################################################## 444 # Variables 445 ######################################################################## 446 447 __all__ = ["Result"] 448

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_result_reader-module.html0000664000076400007640000001120011122067145027367 0ustar stefanstefan qm.test.file_result_reader
Package qm :: Package test :: Module file_result_reader
[hide private]
[frames] | no frames]

Module file_result_reader

source code

Classes [hide private]
  FileResultReader
A 'FileResultReader' gets its input from a file.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_If-module.html0000664000076400007640000002312111122067145030576 0ustar stefanstefan qm.external.DocumentTemplate.DT_If
Package qm :: Package external :: Package DocumentTemplate :: Module DT_If
[hide private]
[frames] | no frames]

Module DT_If

source code

Conditional insertion

Conditional insertion is performed using 'if' and 'else'
commands.

To include text when an object is true using the EPFS
format, use::

   %(if name)[
        text
   %(if name)]

To include text when an object is true using the HTML
format, use::

   <!--#if name-->
        text
   <!--#/if name-->

where 'name' is the name bound to the object.

To include text when an object is false using the EPFS
format, use::

   %(else name)[
        text
   %(else name)]

To include text when an object is false using the HTML
format, use::

   <!--#else name-->
        text
   <!--#/else name-->

Finally to include text when an object is true and to
include different text when the object is false using the
EPFS format, use::

   %(if name)[
        true text
   %(if name)]
   %(else name)[
        false text
   %(else name)]

and to include text when an object is true and to
include different text when the object is false using the
HTML format, use::

   <!--#if name-->
        true text
   <!--#else name-->
        false text
   <!--#/if name-->

Notes:

- if a variable is nor defined, it is considered to be false.

- A variable if only evaluated once in an 'if' tag.  If the value
  is used inside the tag, including in enclosed tags, the
  variable is not reevaluated.


Version: 1069

Classes [hide private]
  If
  Unless
  Else
Variables [hide private]
  __doc__ = '''Conditional insert...
  __rcs_id__ = '$Id: DT_If.py 1069 2008-11-13 21:55:43Z stefan $'
Variables Details [hide private]

__doc__

Value:
'''Conditional insertion

       Conditional insertion is performed using 'if' and 'else'
       commands.

       To include text when an object is true using the EPFS
       format, use::

...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.attachment.FileAttachmentStore-class.html0000664000076400007640000004307311122067145030443 0ustar stefanstefan qm.attachment.FileAttachmentStore
Package qm :: Module attachment :: Class FileAttachmentStore
[hide private]
[frames] | no frames]

Class FileAttachmentStore

source code

     object --+    
              |    
AttachmentStore --+
                  |
                 FileAttachmentStore
Known Subclasses:

An attachment store based on the file system.

The locations are the names of files in the file system.

Instance Methods [hide private]
 
__init__(self, root=None)
Construct a new 'FileAttachmentStore'
source code
 
GetData(self, location)
Return the data for an attachment.
source code
 
GetDataFile(self, location)
Return the path to a file containing the data for 'attachment'.
source code
 
GetSize(self, location)
Return the size of the data for an attachment.
source code
 
Store(self, attachment, location)
Add an attachment to the store.
source code
 
Remove(self, location)
Remove an attachment.
source code

Inherited from AttachmentStore: HandleDownloadRequest

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, root=None)
(Constructor)

source code 

Construct a new 'FileAttachmentStore'

'root' -- If not 'None', the root directory for the store. All locations are relative to this directory. If 'None', all locations are relative to the current directory.

Overrides: object.__init__

GetData(self, location)

source code 

Return the data for an attachment.

returns -- A string containing the attachment data.

Overrides: AttachmentStore.GetData
(inherited documentation)

GetDataFile(self, location)

source code 

Return the path to a file containing the data for 'attachment'.

returns -- A file system path.

The file is read-only, and may be a temporary file. The caller should not modify the file in any way.

Overrides: AttachmentStore.GetDataFile
(inherited documentation)

GetSize(self, location)

source code 

Return the size of the data for an attachment.

returns -- The length of the attachment data, in bytes.

This method may be overridden by derived classes.

Overrides: AttachmentStore.GetSize
(inherited documentation)

Store(self, attachment, location)

source code 

Add an attachment to the store.

'attachment' -- The 'Attachment' to store.

'location' -- The location in which to store the 'attachment'.

Overrides: AttachmentStore.Store
(inherited documentation)

Remove(self, location)

source code 

Remove an attachment.

'location' -- The location whose data should be removed.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command.ShellCommandTest-class.html0000664000076400007640000004430311122067146031642 0ustar stefanstefan qm.test.classes.command.ShellCommandTest
Package qm :: Package test :: Package classes :: Module command :: Class ShellCommandTest
[hide private]
[frames] | no frames]

Class ShellCommandTest

source code

         object --+                
                  |                
extension.Extension --+            
                      |            
      runnable.Runnable --+        
                          |        
                  test.Test --+    
                              |    
                   ExecTestBase --+
                                  |
                                 ShellCommandTest

Check a shell command's output and exit code.

A 'ShellCommandTest' runs the shell and compares its standard output, standard error, and exit code with expected values. The shell may be provided with command-line arguments and/or standard input.

QMTest determines which shell to use by the following method:

  • If the context contains the property 'ShellCommandTest.command_shell', its value is split into an argument list and used.
  • Otherwise, if the '.qmrc' configuration file contains the common property 'command_shell', its value is split into an argument list and used.
  • Otherwise, the default shell for the target system is used.
Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code

Inherited from ExecTestBase: MakeEnvironment, RunProgram, ValidateOutput

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "command", title= "Comm...
A list of the arguments to the extension class.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

Overrides: test.Test.Run

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "command", title= "Command", description= "\
""The arguments to the shell.

            This field contains the arguments that are passed to the
            shell.  It should not contain the path to the shell itself\
.

            If this field is left blank, the shell is run without
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.runnable-module.html0000664000076400007640000001104711122067145025347 0ustar stefanstefan qm.test.runnable
Package qm :: Package test :: Module runnable
[hide private]
[frames] | no frames]

Module runnable

source code

Classes [hide private]
  Runnable
A 'Runnable' can run on a 'Target'.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_HTML-pysrc.html0000664000076400007640000043444011122067154030671 0ustar stefanstefan qm.external.DocumentTemplate.DT_HTML
Package qm :: Package external :: Package DocumentTemplate :: Module DT_HTML
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_HTML

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  """HTML formated DocumentTemplates 
 14   
 15  $Id: DT_HTML.py 1007 2007-02-10 01:07:28Z stefan $""" 
 16   
 17  from DT_String import String, FileMixin 
 18  import DT_String, re 
 19  from DT_Util import ParseError, str 
 20   
21 -class dtml_re_class:
22 """ This needs to be replaced before 2.4. It's a hackaround. """
23 - def search(self, text, start=0, 24 name_match=re.compile('[\000- ]*[a-zA-Z]+[\000- ]*').match, 25 end_match=re.compile('[\000- ]*(/|end)', re.I).match, 26 start_search=re.compile('[<&]').search, 27 ent_name=re.compile('[-a-zA-Z0-9_.]+').match, 28 ):
29 30 while 1: 31 mo = start_search(text,start) 32 if mo is None: return None 33 s = mo.start(0) 34 if text[s:s+5] == '<!--#': 35 n=s+5 36 e=text.find('-->',n) 37 if e < 0: return None 38 en=3 39 40 mo =end_match(text,n) 41 if mo is not None: 42 l = mo.end(0) - mo.start(0) 43 end=text[n:n+l].strip() 44 n=n+l 45 else: end='' 46 47 elif text[s:s+6] == '<dtml-': 48 e=n=s+6 49 while 1: 50 e=text.find('>',e+1) 51 if e < 0: return None 52 if len(text[n:e].split('"'))%2: 53 # check for even number of "s inside 54 break 55 56 en=1 57 end='' 58 59 elif text[s:s+7] == '</dtml-': 60 e=n=s+7 61 while 1: 62 e=text.find('>',e+1) 63 if e < 0: return None 64 if len(text[n:e].split('"'))%2: 65 # check for even number of "s inside 66 break 67 68 en=1 69 end='/' 70 71 else: 72 if text[s:s+5] == '&dtml' and text[s+5] in '.-': 73 n=s+6 74 e=text.find(';',n) 75 if e >= 0: 76 args=text[n:e] 77 l=len(args) 78 mo = ent_name(args) 79 if mo is not None: 80 if mo.end(0)-mo.start(0) == l: 81 d=self.__dict__ 82 if text[s+5]=='-': 83 d[1]=d['end']='' 84 d[2]=d['name']='var' 85 d[0]=text[s:e+1] 86 d[3]=d['args']=args+' html_quote' 87 self._start = s 88 return self 89 else: 90 nn=args.find('-') 91 if nn >= 0 and nn < l-1: 92 d[1]=d['end']='' 93 d[2]=d['name']='var' 94 d[0]=text[s:e+1] 95 args=args[nn+1:]+' '+ \ 96 args[:nn].replace('.',' ') 97 d[3]=d['args']=args 98 self._start = s 99 return self 100 101 start=s+1 102 continue 103 104 break 105 106 mo = name_match(text,n) 107 if mo is None: return None 108 l = mo.end(0) - mo.start(0) 109 110 a=n+l 111 name=text[n:a].strip() 112 113 args=text[a:e].strip() 114 115 d=self.__dict__ 116 d[0]=text[s:e+en] 117 d[1]=d['end']=end 118 d[2]=d['name']=name 119 d[3]=d['args']=args 120 self._start = s 121 return self
122
123 - def group(self, *args):
124 get=self.__dict__.get 125 if len(args)==1: 126 return get(args[0]) 127 return tuple(map(get, args))
128
129 - def start(self, *args):
130 return self._start
131
132 -class HTML(DT_String.String):
133 """HTML Document Templates 134 135 HTML Document templates use HTML server-side-include syntax, 136 rather than Python format-string syntax. Here's a simple example: 137 138 <!--#in results--> 139 <!--#var name--> 140 <!--#/in--> 141 142 HTML document templates quote HTML tags in source when the 143 template is converted to a string. This is handy when templates 144 are inserted into HTML editing forms. 145 """ 146 147 tagre__roles__=()
148 - def tagre(self):
149 return dtml_re_class()
150 151 parseTag__roles__=()
152 - def parseTag(self, match_ob, command=None, sargs=''):
153 """Parse a tag using an already matched re 154 155 Return: tag, args, command, coname 156 157 where: tag is the tag, 158 args is the tag\'s argument string, 159 command is a corresponding command info structure if the 160 tag is a start tag, or None otherwise, and 161 coname is the name of a continue tag (e.g. else) 162 or None otherwise 163 """ 164 tag, end, name, args = match_ob.group(0, 'end', 'name', 'args') 165 args=args.strip() 166 if end: 167 if not command or name != command.name: 168 raise ParseError, ('unexpected end tag', tag) 169 return tag, args, None, None 170 171 if command and name in command.blockContinuations: 172 173 if name=='else' and args: 174 # Waaaaaah! Have to special case else because of 175 # old else start tag usage. Waaaaaaah! 176 l=len(args) 177 if not (args==sargs or 178 args==sargs[:l] and sargs[l:l+1] in ' \t\n'): 179 return tag, args, self.commands[name], None 180 181 return tag, args, None, name 182 183 try: return tag, args, self.commands[name], None 184 except KeyError: 185 raise ParseError, ('Unexpected tag', tag)
186 187 SubTemplate__roles__=()
188 - def SubTemplate(self, name): return HTML('', __name__=name)
189 190 varExtra__roles__=()
191 - def varExtra(self, match_ob): return 's'
192 193 manage_edit__roles__=()
194 - def manage_edit(self,data,REQUEST=None):
195 'edit a template' 196 self.munge(data) 197 if REQUEST: return self.editConfirmation(self,REQUEST)
198 199 quotedHTML__roles__=()
200 - def quotedHTML(self, 201 text=None, 202 character_entities=( 203 (('&'), '&amp;'), 204 (("<"), '&lt;' ), 205 ((">"), '&gt;' ), 206 (('"'), '&quot;'))): #"
207 if text is None: text=self.read_raw() 208 for re,name in character_entities: 209 if text.find(re) >= 0: text=name.join(text.split(re)) 210 return text
211 212 errQuote__roles__=() 213 errQuote=quotedHTML 214
215 - def __str__(self):
216 return self.quotedHTML()
217 218 # these should probably all be deprecated. 219 management_interface__roles__=()
220 - def management_interface(self):
221 '''Hook to allow public execution of management interface with 222 everything else private.''' 223 return self
224 225 manage_editForm__roles__=()
226 - def manage_editForm(self, URL1, REQUEST):
227 '''Display doc template editing form''' #" 228 229 return self._manage_editForm( 230 self, 231 mapping=REQUEST, 232 __str__=str(self), 233 URL1=URL1 234 )
235 236 manage_editDocument__roles__=() 237 manage__roles__=() 238 manage_editDocument=manage=manage_editForm 239
240 -class HTMLDefault(HTML):
241 '''\ 242 HTML document templates that edit themselves through copy. 243 244 This is to make a distinction from HTML objects that should edit 245 themselves in place. 246 ''' 247 copy_class__roles__=() 248 copy_class=HTML 249 250 manage_edit__roles__=()
251 - def manage_edit(self,data,PARENTS,URL1,REQUEST):
252 'edit a template' 253 newHTML=self.copy_class(data,self.globals,self.__name__) 254 setattr(PARENTS[1],URL1[URL1.rfind('/')+1:],newHTML) 255 return self.editConfirmation(self,REQUEST)
256 257
258 -class HTMLFile(FileMixin, HTML):
259 """\ 260 HTML Document templates read from files. 261 262 If the object is pickled, the file name, rather 263 than the file contents is pickled. When the object is 264 unpickled, then the file will be re-read to obtain the string. 265 Note that the file will not be read until the document 266 template is used the first time. 267 """ 268 manage_default__roles__=()
269 - def manage_default(self, REQUEST=None):
270 'Revert to factory defaults' 271 if self.edited_source: 272 self.edited_source='' 273 self._v_cooked=self.cook() 274 if REQUEST: return self.editConfirmation(self,REQUEST)
275 276 manage_editForm__roles__=()
277 - def manage_editForm(self, URL1, REQUEST):
278 '''Display doc template editing form''' 279 280 return self._manage_editForm(mapping=REQUEST, 281 document_template_edit_width= 282 self.document_template_edit_width, 283 document_template_edit_header= 284 self.document_template_edit_header, 285 document_template_form_header= 286 self.document_template_form_header, 287 document_template_edit_footer= 288 self.document_template_edit_footer, 289 URL1=URL1, 290 __str__=str(self), 291 FactoryDefaultString=FactoryDefaultString, 292 )
293 manage_editDocument__roles__=() 294 manage__roles__=() 295 manage_editDocument=manage=manage_editForm 296 297 manage_edit__roles__=()
298 - def manage_edit(self,data, 299 PARENTS=[],URL1='',URL2='',REQUEST='', SUBMIT=''):
300 'edit a template' 301 if SUBMIT==FactoryDefaultString: return self.manage_default(REQUEST) 302 if data.find('\r'): 303 data='\n\r'.join(data.split('\r\n')) 304 data='\n'.join(data.split('\n\r')) 305 306 if self.edited_source: 307 self.edited_source=data 308 self._v_cooked=self.cook() 309 else: 310 __traceback_info__=self.__class__ 311 newHTML=self.__class__() 312 newHTML.__setstate__(self.__getstate__()) 313 newHTML.edited_source=data 314 setattr(PARENTS[1],URL1[URL1.rfind('/')+1:],newHTML) 315 if REQUEST: return self.editConfirmation(self,REQUEST)
316

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.NoSuchItemError-class.html0000664000076400007640000002611211122067150030147 0ustar stefanstefan qm.test.database.NoSuchItemError
qm :: test :: database :: NoSuchItemError :: Class NoSuchItemError
[hide private]
[frames] | no frames]

Class NoSuchItemError

source code

              object --+                
                       |                
exceptions.BaseException --+            
                           |            
        exceptions.Exception --+        
                               |        
              common.QMException --+    
                                   |    
                       DatabaseError --+
                                       |
                                      NoSuchItemError
Known Subclasses:

An exception indicating that a particular item could not be found.

Instance Methods [hide private]
 
__init__(self, kind, item_id)
Construct a new 'QMException'.
source code
 
__str__(self)
Return a string describing this exception.
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, kind, item_id)
(Constructor)

source code 

Construct a new 'QMException'.

'message' -- A string describing the cause of the message as structured text. If this exception is not handled, the 'message' will be displayed as an error message.

Overrides: object.__init__
(inherited documentation)

__str__(self)
(Informal representation operator)

source code 

Return a string describing this exception.

Overrides: object.__str__

qmtest-2.4.1/share/doc/qmtest/html/manual/epydoc.css0000664000076400007640000003722711122067143022001 0ustar stefanstefan /* Epydoc CSS Stylesheet * * This stylesheet can be used to customize the appearance of epydoc's * HTML output. * */ /* Default Colors & Styles * - Set the default foreground & background color with 'body'; and * link colors with 'a:link' and 'a:visited'. * - Use bold for decision list terms. * - The heading styles defined here are used for headings *within* * docstring descriptions. All headings used by epydoc itself use * either class='epydoc' or class='toc' (CSS styles for both * defined below). */ body { background: #ffffff; color: #000000; } p { margin-top: 0.5em; margin-bottom: 0.5em; } a:link { color: #0000ff; } a:visited { color: #204080; } dt { font-weight: bold; } h1 { font-size: +140%; font-style: italic; font-weight: bold; } h2 { font-size: +125%; font-style: italic; font-weight: bold; } h3 { font-size: +110%; font-style: italic; font-weight: normal; } code { font-size: 100%; } /* N.B.: class, not pseudoclass */ a.link { font-family: monospace; } /* Page Header & Footer * - The standard page header consists of a navigation bar (with * pointers to standard pages such as 'home' and 'trees'); a * breadcrumbs list, which can be used to navigate to containing * classes or modules; options links, to show/hide private * variables and to show/hide frames; and a page title (using *

). The page title may be followed by a link to the * corresponding source code (using 'span.codelink'). * - The footer consists of a navigation bar, a timestamp, and a * pointer to epydoc's homepage. */ h1.epydoc { margin: 0; font-size: +140%; font-weight: bold; } h2.epydoc { font-size: +130%; font-weight: bold; } h3.epydoc { font-size: +115%; font-weight: bold; margin-top: 0.2em; } td h3.epydoc { font-size: +115%; font-weight: bold; margin-bottom: 0; } table.navbar { background: #a0c0ff; color: #000000; border: 2px groove #c0d0d0; } table.navbar table { color: #000000; } th.navbar-select { background: #70b0ff; color: #000000; } table.navbar a { text-decoration: none; } table.navbar a:link { color: #0000ff; } table.navbar a:visited { color: #204080; } span.breadcrumbs { font-size: 85%; font-weight: bold; } span.options { font-size: 70%; } span.codelink { font-size: 85%; } td.footer { font-size: 85%; } /* Table Headers * - Each summary table and details section begins with a 'header' * row. This row contains a section title (marked by * 'span.table-header') as well as a show/hide private link * (marked by 'span.options', defined above). * - Summary tables that contain user-defined groups mark those * groups using 'group header' rows. */ td.table-header { background: #70b0ff; color: #000000; border: 1px solid #608090; } td.table-header table { color: #000000; } td.table-header table a:link { color: #0000ff; } td.table-header table a:visited { color: #204080; } span.table-header { font-size: 120%; font-weight: bold; } th.group-header { background: #c0e0f8; color: #000000; text-align: left; font-style: italic; font-size: 115%; border: 1px solid #608090; } /* Summary Tables (functions, variables, etc) * - Each object is described by a single row of the table with * two cells. The left cell gives the object's type, and is * marked with 'code.summary-type'. The right cell gives the * object's name and a summary description. * - CSS styles for the table's header and group headers are * defined above, under 'Table Headers' */ table.summary { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin-bottom: 0.5em; } td.summary { border: 1px solid #608090; } code.summary-type { font-size: 85%; } table.summary a:link { color: #0000ff; } table.summary a:visited { color: #204080; } /* Details Tables (functions, variables, etc) * - Each object is described in its own div. * - A single-row summary table w/ table-header is used as * a header for each details section (CSS style for table-header * is defined above, under 'Table Headers'). */ table.details { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin: .2em 0 0 0; } table.details table { color: #000000; } table.details a:link { color: #0000ff; } table.details a:visited { color: #204080; } /* Fields */ dl.fields { margin-left: 2em; margin-top: 1em; margin-bottom: 1em; } dl.fields dd ul { margin-left: 0em; padding-left: 0em; } dl.fields dd ul li ul { margin-left: 2em; padding-left: 0em; } div.fields { margin-left: 2em; } div.fields p { margin-bottom: 0.5em; } /* Index tables (identifier index, term index, etc) * - link-index is used for indices containing lists of links * (namely, the identifier index & term index). * - index-where is used in link indices for the text indicating * the container/source for each link. * - metadata-index is used for indices containing metadata * extracted from fields (namely, the bug index & todo index). */ table.link-index { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; } td.link-index { border-width: 0px; } table.link-index a:link { color: #0000ff; } table.link-index a:visited { color: #204080; } span.index-where { font-size: 70%; } table.metadata-index { border-collapse: collapse; background: #e8f0f8; color: #000000; border: 1px solid #608090; margin: .2em 0 0 0; } td.metadata-index { border-width: 1px; border-style: solid; } table.metadata-index a:link { color: #0000ff; } table.metadata-index a:visited { color: #204080; } /* Function signatures * - sig* is used for the signature in the details section. * - .summary-sig* is used for the signature in the summary * table, and when listing property accessor functions. * */ .sig-name { color: #006080; } .sig-arg { color: #008060; } .sig-default { color: #602000; } .summary-sig { font-family: monospace; } .summary-sig-name { color: #006080; font-weight: bold; } table.summary a.summary-sig-name:link { color: #006080; font-weight: bold; } table.summary a.summary-sig-name:visited { color: #006080; font-weight: bold; } .summary-sig-arg { color: #006040; } .summary-sig-default { color: #501800; } /* Subclass list */ ul.subclass-list { display: inline; } ul.subclass-list li { display: inline; } /* To render variables, classes etc. like functions */ table.summary .summary-name { color: #006080; font-weight: bold; font-family: monospace; } table.summary a.summary-name:link { color: #006080; font-weight: bold; font-family: monospace; } table.summary a.summary-name:visited { color: #006080; font-weight: bold; font-family: monospace; } /* Variable values * - In the 'variable details' sections, each varaible's value is * listed in a 'pre.variable' box. The width of this box is * restricted to 80 chars; if the value's repr is longer than * this it will be wrapped, using a backslash marked with * class 'variable-linewrap'. If the value's repr is longer * than 3 lines, the rest will be ellided; and an ellipsis * marker ('...' marked with 'variable-ellipsis') will be used. * - If the value is a string, its quote marks will be marked * with 'variable-quote'. * - If the variable is a regexp, it is syntax-highlighted using * the re* CSS classes. */ pre.variable { padding: .5em; margin: 0; background: #dce4ec; color: #000000; border: 1px solid #708890; } .variable-linewrap { color: #604000; font-weight: bold; } .variable-ellipsis { color: #604000; font-weight: bold; } .variable-quote { color: #604000; font-weight: bold; } .variable-group { color: #008000; font-weight: bold; } .variable-op { color: #604000; font-weight: bold; } .variable-string { color: #006030; } .variable-unknown { color: #a00000; font-weight: bold; } .re { color: #000000; } .re-char { color: #006030; } .re-op { color: #600000; } .re-group { color: #003060; } .re-ref { color: #404040; } /* Base tree * - Used by class pages to display the base class hierarchy. */ pre.base-tree { font-size: 80%; margin: 0; } /* Frames-based table of contents headers * - Consists of two frames: one for selecting modules; and * the other listing the contents of the selected module. * - h1.toc is used for each frame's heading * - h2.toc is used for subheadings within each frame. */ h1.toc { text-align: center; font-size: 105%; margin: 0; font-weight: bold; padding: 0; } h2.toc { font-size: 100%; font-weight: bold; margin: 0.5em 0 0 -0.3em; } /* Syntax Highlighting for Source Code * - doctest examples are displayed in a 'pre.py-doctest' block. * If the example is in a details table entry, then it will use * the colors specified by the 'table pre.py-doctest' line. * - Source code listings are displayed in a 'pre.py-src' block. * Each line is marked with 'span.py-line' (used to draw a line * down the left margin, separating the code from the line * numbers). Line numbers are displayed with 'span.py-lineno'. * The expand/collapse block toggle button is displayed with * 'a.py-toggle' (Note: the CSS style for 'a.py-toggle' should not * modify the font size of the text.) * - If a source code page is opened with an anchor, then the * corresponding code block will be highlighted. The code * block's header is highlighted with 'py-highlight-hdr'; and * the code block's body is highlighted with 'py-highlight'. * - The remaining py-* classes are used to perform syntax * highlighting (py-string for string literals, py-name for names, * etc.) */ pre.py-doctest { padding: .5em; margin: 1em; background: #e8f0f8; color: #000000; border: 1px solid #708890; } table pre.py-doctest { background: #dce4ec; color: #000000; } pre.py-src { border: 2px solid #000000; background: #f0f0f0; color: #000000; } .py-line { border-left: 2px solid #000000; margin-left: .2em; padding-left: .4em; } .py-lineno { font-style: italic; font-size: 90%; padding-left: .5em; } a.py-toggle { text-decoration: none; } div.py-highlight-hdr { border-top: 2px solid #000000; border-bottom: 2px solid #000000; background: #d8e8e8; } div.py-highlight { border-bottom: 2px solid #000000; background: #d0e0e0; } .py-prompt { color: #005050; font-weight: bold;} .py-more { color: #005050; font-weight: bold;} .py-string { color: #006030; } .py-comment { color: #003060; } .py-keyword { color: #600000; } .py-output { color: #404040; } .py-name { color: #000050; } .py-name:link { color: #000050 !important; } .py-name:visited { color: #000050 !important; } .py-number { color: #005000; } .py-defname { color: #000060; font-weight: bold; } .py-def-name { color: #000060; font-weight: bold; } .py-base-class { color: #000060; } .py-param { color: #000060; } .py-docstring { color: #006030; } .py-decorator { color: #804020; } /* Use this if you don't want links to names underlined: */ /*a.py-name { text-decoration: none; }*/ /* Graphs & Diagrams * - These CSS styles are used for graphs & diagrams generated using * Graphviz dot. 'img.graph-without-title' is used for bare * diagrams (to remove the border created by making the image * clickable). */ img.graph-without-title { border: none; } img.graph-with-title { border: 1px solid #000000; } span.graph-title { font-weight: bold; } span.graph-caption { } /* General-purpose classes * - 'p.indent-wrapped-lines' defines a paragraph whose first line * is not indented, but whose subsequent lines are. * - The 'nomargin-top' class is used to remove the top margin (e.g. * from lists). The 'nomargin' class is used to remove both the * top and bottom margin (but not the left or right margin -- * for lists, that would cause the bullets to disappear.) */ p.indent-wrapped-lines { padding: 0 0 0 7em; text-indent: -7em; margin: 0; } .nomargin-top { margin-top: 0; } .nomargin { margin-top: 0; margin-bottom: 0; } /* HTML Log */ div.log-block { padding: 0; margin: .5em 0 .5em 0; background: #e8f0f8; color: #000000; border: 1px solid #000000; } div.log-error { padding: .1em .3em .1em .3em; margin: 4px; background: #ffb0b0; color: #000000; border: 1px solid #000000; } div.log-warning { padding: .1em .3em .1em .3em; margin: 4px; background: #ffffb0; color: #000000; border: 1px solid #000000; } div.log-info { padding: .1em .3em .1em .3em; margin: 4px; background: #b0ffb0; color: #000000; border: 1px solid #000000; } h2.log-hdr { background: #70b0ff; color: #000000; margin: 0; padding: 0em 0.5em 0em 0.5em; border-bottom: 1px solid #000000; font-size: 110%; } p.log { font-weight: bold; margin: .5em 0 .5em 0; } tr.opt-changed { color: #000000; font-weight: bold; } tr.opt-default { color: #606060; } pre.log { margin: 0; padding: 0; padding-left: 1em; } qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.resource_adapter-module.html0000664000076400007640000001120011122067145027057 0ustar stefanstefan qm.test.resource_adapter
Package qm :: Package test :: Module resource_adapter
[hide private]
[frames] | no frames]

Module resource_adapter

source code

Classes [hide private]
  ResourceAdapter
A 'ResourceAdapter' converts test classes to resource classes.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.mount_database-module.html0000664000076400007640000001130711122067145030162 0ustar stefanstefan qm.test.classes.mount_database
Package qm :: Package test :: Package classes :: Module mount_database
[hide private]
[frames] | no frames]

Module mount_database

source code

Classes [hide private]
  MountDatabase
A 'MountDatabase' contains other databases.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.platform_win32-module.html0000664000076400007640000000316211122067144026212 0ustar stefanstefan platform_win32

Module platform_win32


Classes

SignalException

Functions

get_host_name
open_in_browser

Variables

default_shell

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-G.html0000664000076400007640000027151311122067144024304 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

G



qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-P.html0000664000076400007640000006070411122067144024313 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

P



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.diagnostic-module.html0000664000076400007640000003503511122067145024712 0ustar stefanstefan qm.diagnostic
Package qm :: Module diagnostic
[hide private]
[frames] | no frames]

Module diagnostic

source code

Table-based diagnostic message generation.

Diagnostics are loaded from text files.  These files are laid out
according to special rules:

  - Lines beginning with a hash mark are ignored.

  - Each diagnostic begins with a line that contains an at sign (@) and
    a tag used to identify the diagnostic.

  - Subsequent text until the start of the next diagnostic is
    the diagnostic template.

  - Diagnostic templates may contain named-substition tokens as
    used by the Python % operator on a string.

  - Diagnostic messages are interpreted as structured text.

For example:

    # This line is a comment

    @ my first diagnostic
    The command you entered, '$(command)s', is bogus.  Please try again.

    @ my second diagnostic
    The value you specified, '$(value)d', is completely bogus.  Don't
    even bother trying again.

Classes [hide private]
  DiagnosticSet
Functions [hide private]
 
get_diagnostic_set()
Return the 'DiagnosticSet' containing warning/error messages.
source code
 
get_help_set()
Return the 'DiagnosticSet' for help messages.
source code
 
message(tag, **substitutions)
Generate a diagnostic message.
source code
 
error(tag, output=None, **substitutions)
Generate or emit an error diagnostic.
source code
 
warning(tag, output=None, **substitutions)
Generate or emit a warning diagnostic.
source code
 
load_messages(tool)
Read messages that apply to 'tool'.
source code
Variables [hide private]
  __diagnostic_set = None
The 'DiagnosticSet' object from which diagnostics are generated.
  __help_set = None
The 'DiagnosticSet'object from which help text messages are generated.
Function Details [hide private]

get_diagnostic_set()

source code 

Return the 'DiagnosticSet' containing warning/error messages.

returns -- The 'DiagnosticSet' containing warning/error messages.

get_help_set()

source code 

Return the 'DiagnosticSet' for help messages.

returns -- The 'DiagnosticSet' containing help messages.

load_messages(tool)

source code 

Read messages that apply to 'tool'.

'tool' -- A string giving the name of a QM tool.


././@LongLink0000000000000000000000000000015600000000000011567 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable-c0000664000076400007640000002433711122067147032767 0ustar stefanstefan qm.test.classes.dejagnu_test.DejaGNUTest.BuildExecutable
Package qm :: Package test :: Package classes :: Module dejagnu_test :: Class DejaGNUTest :: Class BuildExecutable
[hide private]
[frames] | no frames]

Class BuildExecutable

source code

              object --+            
                       |            
   executable.Executable --+        
                           |        
executable.TimeoutExecutable --+    
                               |    
 executable.RedirectedExecutable --+
                                   |
                                  DejaGNUTest.BuildExecutable

A 'BuildExecutable' runs on the build machine.

Classes derived from 'DejaGNUTest' may provide derived versions of this class.

Instance Methods [hide private]
 
_StderrPipe(self)
Return a pipe to which to redirect the standard input.
source code

Inherited from executable.RedirectedExecutable (private): _ClosePipeEnd, _CreatePipe, _DoParent, _HandleChild, _InitializeChild, _InitializeParent, _ReadStderr, _ReadStdout, _StdinPipe, _StdoutPipe, _WriteStdin

Inherited from executable.TimeoutExecutable: Run, __init__

Inherited from executable.Executable: Kill, Spawn

Inherited from executable.Executable (private): _GetChildPID

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

_StderrPipe(self)

source code 

Return a pipe to which to redirect the standard input.

returns -- A pipe, or 'None'. If 'None' is returned, but '_StdoutPipe' returns a pipe, then the standard error and standard input will both be redirected to that pipe. However, if '_StdoutPipe' also returns 'None', then the standard error will be closed in the child.

Overrides: executable.RedirectedExecutable._StderrPipe
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test.TargetGroupField-class.html0000664000076400007640000002710311122067150027542 0ustar stefanstefan qm.test.test.TargetGroupField
Package qm :: Package test :: Module test :: Class TargetGroupField
[hide private]
[frames] | no frames]

Class TargetGroupField

source code

  object --+        
           |        
fields.Field --+    
               |    
fields.TextField --+
                   |
                  TargetGroupField

A 'TargetGroupField' contains a target group pattern.

A target group pattern is a regular expression. A test will only be run on a particular target if the target's group is matched by the test's target group pattern.

Instance Methods [hide private]
 
GetDescription(self)
Return a description of this field.
source code

Inherited from fields.TextField: FormatValueAsHtml, FormatValueAsText, GetHelp, GetValueFromDomNode, MakeDomNodeForValue, ParseFormValue, ParseTextValue, Validate, __init__

Inherited from fields.Field: GetBriefDescription, GetDefaultValue, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from fields.Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

GetDescription(self)

source code 

Return a description of this field.

This description is used when displaying detailed help information about the field.

Overrides: fields.Field.GetDescription

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.InvalidSessionError-class.html0000664000076400007640000001537111122067151027124 0ustar stefanstefan qm.web.InvalidSessionError
Package qm :: Module web :: Class InvalidSessionError
[hide private]
[frames] | no frames]

Class InvalidSessionError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  InvalidSessionError

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external-module.html0000664000076400007640000002040011122067145024376 0ustar stefanstefan qm.external
Package qm :: Package external
[hide private]
[frames] | no frames]

Package external

source code

Submodules [hide private]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.rsh_target-pysrc.html0000664000076400007640000017316211122067161027217 0ustar stefanstefan qm.test.classes.rsh_target
Package qm :: Package test :: Package classes :: Module rsh_target
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.rsh_target

 1  ######################################################################## 
 2  # 
 3  # File:   rsh_target.py 
 4  # Author: Mark Mitchell 
 5  # Date:   10/30/2001 
 6  # 
 7  # Contents: 
 8  #   RSHTarget 
 9  # 
10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from   process_target import * 
21  import string 
22   
23  ######################################################################## 
24  # Classes 
25  ######################################################################## 
26   
27 -class RSHTarget(ProcessTarget):
28 """A target that runs tests via a remote shell invocation. 29 30 A 'RSHTarget' runs tests on a remote computer via a remote shell 31 call. The remote shell is in the style of 'rsh' and 'ssh'. Using 32 the remote shell, the target invokes the 'qmtest remote' script, 33 which services commands sent via 'stdin', and replies via 34 'stdout'.""" 35 36 host = qm.fields.TextField( 37 title="Remote Host Name", 38 description="""The name of the host on which to run tests. 39 40 The name (or IP address) of the host on which QMTest 41 should execute tests. If this value is the empty string, 42 the name of the target is used.""") 43 remote_shell = qm.fields.TextField( 44 title="Remote Shell Program", 45 description="""The path to the remote shell program. 46 47 The name of the program that can be used to create a 48 remote shell. This program must accept the same command 49 line arguments as the 'rsh' program.""", 50 default_value="ssh") 51 arguments = qm.fields.TextField( 52 title="Remote Shell Arguments", 53 description="""The arguments to provide to the remote shell. 54 55 A space-separated list of arguments to provide to the 56 remote shell program.""", 57 default_value="") 58 59 60
61 - def __init__(self, database, properties):
62 """Construct a new 'RSHTarget'. 63 64 'database' -- The 'Database' containing the tests that will be 65 run. 66 67 'properties' -- A dictionary mapping strings (property names) 68 to strings (property values).""" 69 70 # Because "arguments" is both a field name and class variable, 71 # the usual default handling of field arguments will not work 72 # corectly; we must explicitly set the default value. 73 if not properties.has_key("arguments"): 74 properties["arguments"] = "" 75 76 # Initialize the base class. 77 ProcessTarget.__init__(self, database, properties) 78 79 # Use the target name as the default name for the remote host. 80 if not self.host: 81 self.host = self.GetName()
82 83
84 - def _GetInterpreter(self):
85 86 # Determine the remote shell program to use. 87 remote_shell_program = self.remote_shell 88 if not remote_shell_program: 89 remote_shell_program = qm.rc.Get("remote_shell", 90 default="ssh", 91 section="common") 92 # Extra command-line arguments to the remote shell program 93 # may be specified with the "arguments" property. 94 arguments = self.arguments.split() 95 96 return [remote_shell_program] + arguments + [self.host]
97

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.mount_database-pysrc.html0000664000076400007640000046416711122067156030057 0ustar stefanstefan qm.test.classes.mount_database
Package qm :: Package test :: Package classes :: Module mount_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.mount_database

  1  ######################################################################## 
  2  # 
  3  # File:   mount_database.py 
  4  # Author: Mark Mitchell 
  5  # Date:   03/19/2003 
  6  # 
  7  # Contents: 
  8  #   MountDatabase 
  9  # 
 10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ######################################################################## 
 17   
 18  import dircache 
 19  import os.path 
 20  from   qm.test.database import * 
 21  from   qm.test.suite import Suite 
 22  from   qm.fields import * 
 23  import qm.test.database 
 24   
 25  ######################################################################## 
 26  # Classes 
 27  ######################################################################## 
 28   
29 -class MountDatabase(Database):
30 """A 'MountDatabase' contains other databases. 31 32 Every contained database has a "mount point", which is a label 33 giving the root of the database. A test with the ID "x" in a 34 database with a mount point of "y" has the ID "x.y" in the 35 containing database. 36 37 The contained databases are found by looking for subdirectories of 38 the 'MountDatabase' directory. Every immediate subdirectory which 39 is itself a QMTest database is mounted; its mount point is the 40 name of the subdirectory.""" 41
42 - class MountedSuite(Suite):
43 """A 'MountedSuite' is a suite from a mounted database.""" 44
45 - def __init__(self, database, suite_id, joiner, suite):
46 47 super(MountDatabase.MountedSuite, self).\ 48 __init__({}, 49 qmtest_id = suite_id, 50 qmtest_database = database) 51 self.__suite = suite 52 self.__joiner = joiner
53 54
55 - def IsImplicit(self):
56 57 return self.__suite.IsImplicit()
58 59
60 - def GetTestIds(self):
61 62 return map(self.__joiner, self.__suite.GetTestIds())
63 64
65 - def GetSuiteIds(self):
66 67 return map(self.__joiner, self.__suite.GetSuiteIds())
68 69 70 mounts = DictionaryField(key_field = TextField(), 71 value_field = TextField(), 72 description=\ 73 """Dictionary mapping mount points to (sub-)database paths. 74 If empty, the database directory is scanned for subdirectories.""") 75 76
77 - def __init__(self, path, arguments):
78 79 # The label class used by the MountDatabase is the label class 80 # used by the databases it contains. They must all use the 81 # same label class. 82 label_class = None 83 implicit = False 84 # Find the contained databases. 85 self.mounts = arguments.pop('mounts', {}) 86 self._mounts = {} 87 if not self.mounts: 88 # Scan local directory. 89 implicit = True 90 self.mounts = dict([(d, os.path.join(path, d)) 91 for d in dircache.listdir(path)]) 92 else: 93 # Translate relative paths into absolute paths. 94 tmp = {} 95 for k,v in self.mounts.iteritems(): 96 tmp[k] = os.path.join(path, v) 97 self.mounts = tmp 98 # Now translate the value from path to database 99 for k,v in self.mounts.iteritems(): 100 if is_database(v): 101 db = load_database(v) 102 self._mounts[k] = db 103 if not label_class: 104 label_class = db.label_class 105 elif label_class != db.label_class: 106 raise QMException, \ 107 "mounted databases use differing label classes" 108 elif not implicit: 109 raise QMException, "%s does not contain a test database"%v 110 111 # Initialize the base class. 112 arguments["modifiable"] = "false" 113 if label_class: 114 arguments["label_class"] = label_class 115 116 Database.__init__(self, path, arguments)
117 118 119
120 - def GetIds(self, kind, directory="", scan_subdirs=1):
121 122 ids = [] 123 if directory == "" and kind == Database.SUITE: 124 ids.extend(self._mounts.keys()) 125 if scan_subdirs: 126 dirs = directory and [directory] or self._mounts.keys() 127 for d in dirs: 128 database, joiner, subdir = self._SelectDatabase(d) 129 ids += [joiner(i) for i in database.GetIds(kind, subdir, 1)] 130 return ids
131
132 - def GetTest(self, test_id):
133 134 joiner, contained_test \ 135 = self._GetContainedItem(Database.TEST, test_id) 136 137 # Remap the prerequisites. 138 arguments = contained_test.GetArguments() 139 prerequisites = contained_test.GetPrerequisites() 140 if prerequisites: 141 new_prerequisites = map(lambda p: (joiner(p[0]), p[1]), 142 prerequisites.items()) 143 arguments[Test.PREREQUISITES_FIELD_ID] = new_prerequisites 144 145 # Remap the resources. 146 self._AdjustResources(joiner, arguments) 147 148 return TestDescriptor(self, 149 test_id, 150 contained_test.GetClassName(), 151 arguments)
152 153
154 - def GetResource(self, resource_id):
155 156 joiner, contained_resource \ 157 = self._GetContainedItem(Database.RESOURCE, resource_id) 158 159 # Remap the resources. 160 arguments = contained_resource.GetArguments() 161 self._AdjustResources(joiner, arguments) 162 163 return ResourceDescriptor(self, resource_id, 164 contained_resource.GetClassName(), 165 arguments)
166 167
168 - def GetSuite(self, suite_id):
169 170 if suite_id == "": 171 return Database.GetSuite(self, suite_id) 172 173 joiner, contained_suite \ 174 = self._GetContainedItem(Database.SUITE, suite_id) 175 test_ids = map(joiner, contained_suite.GetTestIds()) 176 suite_ids = map(joiner, contained_suite.GetSuiteIds()) 177 return MountDatabase.MountedSuite(self, suite_id, 178 joiner, 179 contained_suite)
180 181
182 - def GetSubdirectories(self, directory):
183 184 if directory == "": 185 return self._mounts.keys() 186 database, joiner, dir = self._SelectDatabase(directory) 187 return database.GetSubdirectories(dir)
188 189
190 - def GetClassPaths(self):
191 192 paths = [] 193 for db in self._mounts.values(): 194 paths.extend(db.GetClassPaths()) 195 paths.append(get_configuration_directory(db.GetPath())) 196 return paths
197 198
199 - def _AdjustResources(self, joiner, arguments):
200 """Adjust the resource IDs stored in the 'arguments'. 201 202 'joiner' -- A function of one argument which prepends the 203 label for a mount point to the label it is given. 204 205 'arguments' -- The arguments to a test or resource class. 206 207 Modifies the arguments to contain resource names that are 208 relative to the containing database.""" 209 210 resources = arguments.get(Runnable.RESOURCE_FIELD_ID) 211 if resources: 212 new_resources = map(joiner, resources) 213 arguments[Runnable.RESOURCE_FIELD_ID] = new_resources
214 215
216 - def _GetContainedItem(self, kind, item_id):
217 """Return 'item_id' from a mounted database. 218 219 'kind' -- The kind of item to return. 220 221 'item_id' -- The name of the item, in the containing 222 database. 223 224 returns -- A tuple '(joiner, item). The 'item' will be from 225 one of the mounted databases. 'joiner' is a function of one 226 argument which prepends the mount point to its argument.""" 227 228 try: 229 database, joiner, item_id = self._SelectDatabase(item_id) 230 231 # Look for the item in the contained database. 232 try: 233 item = database.GetItem(kind, item_id) 234 except NoSuchItemError, e: 235 # Reset the id. 236 e.item_id = joiner(item_id) 237 raise 238 239 return joiner, item 240 except: 241 raise Database._item_exceptions[kind](item_id)
242 243
244 - def _SelectDatabase(self, item_id):
245 """Return the contained database in which 'item_id' can be found. 246 247 'item_id' -- The name of an item in this database. 248 249 returns -- A tuple '(database, joiner, id)' where 'database' 250 is a 'Database', 'joiner' is a function of one argument which 251 prepends the mount point to a label, and 'id' is the portion 252 of 'item_id' that remains after stripping off the mount point 253 of 'database'. If 'item_id' does not correspond to any mount 254 point, an exception is raised.""" 255 256 mount_point, item_id = self.SplitLabelLeft(item_id) 257 db = self._mounts[mount_point] 258 return (db, lambda p: self.JoinLabels(mount_point, p), item_id)
259

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dir_run_database-module.html0000664000076400007640000001133611122067145030464 0ustar stefanstefan qm.test.classes.dir_run_database
Package qm :: Package test :: Package classes :: Module dir_run_database
[hide private]
[frames] | no frames]

Module dir_run_database

source code

Classes [hide private]
  DirRunDatabase
A 'DirRunDatabase' reads test runs from a directory.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.executable.RedirectedExecutable-class.html0000664000076400007640000007323511122067146030607 0ustar stefanstefan qm.executable.RedirectedExecutable
Package qm :: Module executable :: Class RedirectedExecutable
[hide private]
[frames] | no frames]

Class RedirectedExecutable

source code

   object --+        
            |        
   Executable --+    
                |    
TimeoutExecutable --+
                    |
                   RedirectedExecutable

A 'RedirectedExecutable' redirects the standard I/O streams.

Instance Methods [hide private]
 
_InitializeParent(self)
Initialize the parent process.
source code
 
_InitializeChild(self)
Initialize the child process.
source code
 
_HandleChild(self)
Run in the parent process after the child has been created.
source code
 
_DoParent(self)
Perform actions required in the parent after 'Spawn'.
source code
 
_ReadStdout(self)
Read from the standard output pipe.
source code
 
_ReadStderr(self)
Read from the standard error pipe.
source code
 
_WriteStdin(self)
Write to the standard input pipe.
source code
 
_StdinPipe(self)
Return a pipe to which to redirect the standard input.
source code
 
_StdoutPipe(self)
Return a pipe to which to redirect the standard output.
source code
 
_StderrPipe(self)
Return a pipe to which to redirect the standard input.
source code
 
_ClosePipeEnd(self, fd)
Close the file descriptor 'fd', which is one end of a pipe.
source code
 
_CreatePipe(self)
Return a new pipe.
source code
 
__CallUntilNone(self, f, attribute)
Call 'f' until 'self.attribute' is 'None'.
source code
 
__UninheritableHandle(self, handle)
Return a duplicate of a file handle that is not inheritable.
source code

Inherited from TimeoutExecutable: Run, __init__

Inherited from Executable: Kill, Spawn

Inherited from Executable (private): _GetChildPID

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

_InitializeParent(self)

source code 

Initialize the parent process.

Before spawning the child, this method is invoked to give the parent a chance to initialize itself.

returns -- Under Windows, a 'PySTARTUPINFO' structure explaining how the child should be initialized. On other systems, the return value is ignored.

Overrides: Executable._InitializeParent
(inherited documentation)

_InitializeChild(self)

source code 

Initialize the child process.

After 'fork' is called this method is invoked to give the child a chance to initialize itself. '_InitializeParent' will already have been called in the parent process.

This method is not used under Windows.

Overrides: Executable._InitializeChild
(inherited documentation)

_HandleChild(self)

source code 

Run in the parent process after the child has been created.

The child process has been spawned; its PID is avialable via '_GetChildPID'. Take any actions in the parent that are required now that the child exists.

Derived class versions must call this method.

Overrides: Executable._HandleChild
(inherited documentation)

_DoParent(self)

source code 

Perform actions required in the parent after 'Spawn'.

Overrides: Executable._DoParent
(inherited documentation)

_WriteStdin(self)

source code 

Write to the standard input pipe.

This implementation writes no data and closes the pipe.

_StdinPipe(self)

source code 

Return a pipe to which to redirect the standard input.

returns -- A pipe, or 'None' if the standard input should be closed in the child.

_StdoutPipe(self)

source code 

Return a pipe to which to redirect the standard output.

returns -- A pipe, or 'None' if the standard output should be closed in the child.

_StderrPipe(self)

source code 

Return a pipe to which to redirect the standard input.

returns -- A pipe, or 'None'. If 'None' is returned, but '_StdoutPipe' returns a pipe, then the standard error and standard input will both be redirected to that pipe. However, if '_StdoutPipe' also returns 'None', then the standard error will be closed in the child.

_ClosePipeEnd(self, fd)

source code 

Close the file descriptor 'fd', which is one end of a pipe.

'fd' -- Under UNIX, a file descriptor. Under Windows, a handle.

_CreatePipe(self)

source code 

Return a new pipe.

returns -- A tuple (under UNIX) or list (under Windows) consisting of the file descriptors (UNIX) or handles (Windows) for the read end and write end of a new pipe. The pipe is inheritable by child processes. On UNIX the fds will not be inherited across 'exec'.

__CallUntilNone(self, f, attribute)

source code 

Call 'f' until 'self.attribute' is 'None'.

'f' -- A callable.

'attribute' -- A string giving the name of an attribute.

__UninheritableHandle(self, handle)

source code 

Return a duplicate of a file handle that is not inheritable.

'handle' -- A file handle.

returns -- A new handle that is a non-inheritable duplicate of the 'handle'.

This method should only be used under Windows.


qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.rsh_target-module.html0000664000076400007640000000212611122067144030117 0ustar stefanstefan rsh_target

Module rsh_target


Classes

RSHTarget

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.local_host.LocalHost-class.html0000664000076400007640000005230111122067147031033 0ustar stefanstefan qm.test.classes.local_host.LocalHost
Package qm :: Package test :: Package classes :: Module local_host :: Class LocalHost
[hide private]
[frames] | no frames]

Class LocalHost

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
              host.Host --+
                          |
                         LocalHost

A 'LocalHost' is the machine on which Python is running.

The default directory for a 'LocalHost' is the current working directory for this Python process.

Nested Classes [hide private]

Inherited from host.Host: Executable

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
UploadFile(self, local_file, remote_file=None)
Copy 'local_file' to 'remote_file'.
source code
 
UploadAndRun(self, path, arguments, environment=None, timeout=-1)
Run a program on the remote host.
source code
 
DownloadFile(self, remote_file, local_file=None)
Copy 'remote_file' to 'local_file'.
source code
 
_SameFile(self, file1, file2)
Return true iff 'file1' and 'file2' are the same file.
source code
 
DeleteFile(self, remote_file)
Delete the 'remote_file'.
source code

Inherited from host.Host: Run, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from host.Host: kind

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

UploadFile(self, local_file, remote_file=None)

source code 

Copy 'local_file' to 'remote_file'.

'local_file' -- The name of the file on the local machine.

'remote_file' -- The name of the file on the remote machine. The 'remote_file' must be a relative path. It is interpreted relative to the default directory. If 'None', the 'remote_file' is placed in the default directory using the basename of the 'local_file'.

If the 'local_file' and 'remote_file' are the same, then this function succeeds, but takes no action.

Overrides: host.Host.UploadFile
(inherited documentation)

UploadAndRun(self, path, arguments, environment=None, timeout=-1)

source code 

Run a program on the remote host.

'path' -- The name of the program to run, as a path on the local machine.

'arguments' -- As for 'Run'.

'environment' -- As for 'Run'.

'timeout' -- As for 'Run'.

returns -- As for 'Run'.

The program is uploaded to the default directory on the remote host, run, and then deleted.

Overrides: host.Host.UploadAndRun
(inherited documentation)

DownloadFile(self, remote_file, local_file=None)

source code 

Copy 'remote_file' to 'local_file'.

'remote_file' -- The name of the file on the remote machine. The 'remote_file' must be a relative path. It is interpreted relative to the default directory.

'local_file' -- The name of the file on the local machine. If 'None', the 'local_file' is placed in the current directory using the basename of the 'remote_file'.

If the 'local_file' and 'remote_file' are the same, then this function succeeds, but takes no action.

Overrides: host.Host.DownloadFile
(inherited documentation)

_SameFile(self, file1, file2)

source code 

Return true iff 'file1' and 'file2' are the same file.

returns -- True iff 'file1' and 'file2' are the same file, even if they have different names.

DeleteFile(self, remote_file)

source code 

Delete the 'remote_file'.

'remote_file' -- A relative path to the file to be deleted.

Overrides: host.Host.DeleteFile
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.PythonField-class.html0000664000076400007640000003107711122067146026103 0ustar stefanstefan qm.fields.PythonField
qm :: fields :: PythonField :: Class PythonField
[hide private]
[frames] | no frames]

Class PythonField

source code

object --+    
         |    
     Field --+
             |
            PythonField

A 'PythonField' stores a Python value.

All 'PythonField's are computed; they are never written out, nor can they be specified directly by users. They are used in situations where the value of the field is specified programatically by the system.

Instance Methods [hide private]
 
__init__(self, name='', default_value=None)
Create a new (generic) field.
source code

Inherited from Field: FormatValueAsHtml, FormatValueAsText, GetBriefDescription, GetDefaultValue, GetDescription, GetHelp, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, GetValueFromDomNode, IsComputed, IsHidden, IsReadOnly, MakeDomNodeForValue, ParseFormValue, ParseTextValue, SetName, Validate, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', default_value=None)
(Constructor)

source code 

Create a new (generic) field.

'name' -- The name of the field.

'default_value' -- The default value for this field.

'title' -- The name given this field when it is displayed in user interfaces.

'description' -- A string explaining the purpose of this field. The 'description' must be provided as structured text. The first line of the structured text must be a one-sentence description of the field; that line is extracted by 'GetBriefDescription'.

'hidden' -- If true, this field is for internal puprpose only and is not shown in user interfaces.

'read_only' -- If true, this field may not be modified by users.

'computed' -- If true, this field is computed automatically. All computed fields are implicitly hidden and implicitly read-only.

The boolean parameters (such as 'hidden') use the convention that true is represented by the string '"true"'; any other value is false. This convention is a historical artifact.

Overrides: object.__init__
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-X.html0000664000076400007640000001712111122067144024316 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

X



qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.diagnostic-module.html0000664000076400007640000000374511122067144025477 0ustar stefanstefan diagnostic

Module diagnostic


Classes

DiagnosticSet

Functions

error
get_diagnostic_set
get_help_set
load_messages
message
warning

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web-module.html0000664000076400007640000001065211122067145024317 0ustar stefanstefan qm.test.web
Package qm :: Package test :: Package web
[hide private]
[frames] | no frames]

Package web

source code

Submodules [hide private]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform-module.html0000664000076400007640000002163411122067145024412 0ustar stefanstefan qm.platform
Package qm :: Module platform
[hide private]
[frames] | no frames]

Module platform

source code

Classes [hide private]
  MailError
Functions [hide private]
 
get_shell_for_command()
Return the command shell to use when running a single shell command.
source code
 
get_shell_for_script()
Return the command shell to use when running a shell script.
source code
Function Details [hide private]

get_shell_for_command()

source code 

Return the command shell to use when running a single shell command.

returns -- A sequence of argument list entries to use when invoking the shell. The first element of the list is the shell executable path. The command should be appended to the argument list.

get_shell_for_script()

source code 

Return the command shell to use when running a shell script.

returns -- A sequence of argument list entries to use when running a shell script. The first element of the list is the shell executable. The name of the script should be appended to the argument list.


././@LongLink0000000000000000000000000000015500000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.pickle_result_stream.PickleResultStream-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.pickle_result_stream.PickleResultStream-cl0000664000076400007640000007270611122067147033357 0ustar stefanstefan qm.test.classes.pickle_result_stream.PickleResultStream
Package qm :: Package test :: Package classes :: Module pickle_result_stream :: Class PickleResultStream
[hide private]
[frames] | no frames]

Class PickleResultStream

source code

                 object --+            
                          |            
        extension.Extension --+        
                              |        
     result_stream.ResultStream --+    
                                  |    
file_result_stream.FileResultStream --+
                                      |
                                     PickleResultStream

A 'PickleResultStream' writes out results as Python pickles.

See also 'PickleResultReader', which does the reverse.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code
 
_ResetPickler(self) source code
 
_WriteAnnotationPtr(self) source code
 
WriteAnnotation(self, key, value)
Output an annotation for this run.
source code
 
WriteResult(self, result)
Output a test result.
source code

Inherited from result_stream.ResultStream: Summarize, WriteAllAnnotations

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  _max_pinned_results = 1000
A limit on how many `Result's to pin in memory at once.
  _format_version = 1
The version number of the format we write.
  arguments = [<<class 'qm.fields.IntegerField'> protocol_version>]
A list of the arguments to the extension class.
  _is_binary_file = 1
If true, the file written is a binary file.
  _argument_dictionary = {'expected_outcomes': <<class 'qm.field...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.PythonField'> expected_ou...
A list of all the 'Field's in this class.
  protocol_version = 1

Inherited from file_result_stream.FileResultStream: file, filename

Inherited from result_stream.ResultStream: expected_outcomes, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

WriteAnnotation(self, key, value)

source code 

Output an annotation for this run.

Subclasses should override this if they want to store/display annotations; the default implementation simply discards them.

'key' -- the key value as a string.

'value' -- the value of this annotation as a string.

Overrides: result_stream.ResultStream.WriteAnnotation
(inherited documentation)

WriteResult(self, result)

source code 

Output a test result.

Subclasses must override this method; the default implementation raises a 'NotImplementedError'.

'result' -- A 'Result'.

Overrides: result_stream.ResultStream.WriteResult
(inherited documentation)

Class Variable Details [hide private]

_max_pinned_results

A limit on how many `Result's to pin in memory at once.

Pickling an object normally pins it in memory; this is necessary to ensure correct behaviour when pickling multiple references to the same object. We know that `Result's can't refer to each other, so this pinning is useless overhead; however, clearing the cache at every call to `WriteResult' slows down both pickling and unpickling by about a factor of two. As a solution, any given `PickleResultStream', will clear its cache after `_max_pinned_results' calls to WriteResult. This cache-clearing technique causes a very minor slowdown on small result streams, and a substantial speedup on large result streams.

Value:
1000

_format_version

The version number of the format we write.

This is bumped every time the format is changed, to make sure that we can retain backwards compatibility.

"Version 0" contains no version number, and is simply a bunch of 'Result's pickled one after another.

"Version 1", and all later versions, contain a pickled version number as the first thing in the file. In version 1, this is followed by a 4-byte unsigned integer in network byte order giving the address of the first annotation, followed by the file proper. The file proper is composed of a bunch of pickled 'Result's, followed by a pickled sentinel value (None), followed by a 4-byte unsigned integer in network-byte order, followed by the beginning of a new pickle whose first item is a annotation tuple, and following items are more 'Result's, and then another sentinel value, and so on. An annotation tuple is a tuple of n items, the first of which is a string tagging the type of annotation, and the rest of which have an interpretation that depends on the tag found. The only tag currently defined is "annotation", which is followed by two string elements giving respectively the key and the value. The 4-byte integers always point to the file address of the next such integer, except for the last, which has a value of 0; they are used to quickly find all annotations.

Value:
1

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'expected_outcomes': <<class 'qm.fields.PythonField'> expected_outcom\
es>,
 'file': <<class 'qm.fields.PythonField'> file>,
 'filename': <<class 'qm.fields.TextField'> filename>,
 'protocol_version': <<class 'qm.fields.IntegerField'> protocol_versio\
n>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.PythonField'> expected_outcomes>,
 <<class 'qm.fields.IntegerField'> protocol_version>,
 <<class 'qm.fields.PythonField'> file>,
 <<class 'qm.fields.TextField'> filename>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.SetField-class.html0000664000076400007640000007646411122067146025366 0ustar stefanstefan qm.fields.SetField
qm :: fields :: SetField :: Class SetField
[hide private]
[frames] | no frames]

Class SetField

source code

object --+    
         |    
     Field --+
             |
            SetField

A field containing zero or more instances of some other field.

All contents must be of the same field type. A set field may not contain sets.

The default field value is set to an empty set.

Instance Methods [hide private]
 
__init__(self, contained, not_empty_set='false', default_value=None, **properties)
Create a set field.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
GetSubfields(self)
Returns the sequence of subfields contained in this field.
source code
 
GetHtmlHelp(self, edit=0)
Generate help text about this field in HTML format.
source code
 
FormatValueAsText(self, value, columns=72)
Return a plain text rendering of a 'value' for this field.
source code
 
FormatValueAsHtml(self, server, value, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
MakeDomNodeForValue(self, value, document)
Generate a DOM element node for a value of this field.
source code
 
Validate(self, value)
Validate a field value.
source code
 
ParseTextValue(self, value)
Parse a value represented as a string.
source code
 
ParseFormValue(self, request, name, attachment_stores)
Convert a value submitted from an HTML form.
source code
 
GetValueFromDomNode(self, node, attachment_store)
Return a value for this field represented by DOM 'node'.
source code

Inherited from Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetName, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, contained, not_empty_set='false', default_value=None, **properties)
(Constructor)

source code 

Create a set field.

The name of the contained field is taken as the name of this field.

'contained' -- An 'Field' instance describing the elements of the set.

'not_empty_set' -- If true, this field may not be empty, i.e. the value of this field must contain at least one element.

raises -- 'ValueError' if 'contained' is a set field.

raises -- 'TypeError' if 'contained' is not a 'Field'.

Overrides: object.__init__

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: Field.GetHelp
(inherited documentation)

GetSubfields(self)

source code 

Returns the sequence of subfields contained in this field.

returns -- The sequence of subfields contained in this field. If there are no subfields, an empty sequence is returned.

Overrides: Field.GetSubfields
(inherited documentation)

GetHtmlHelp(self, edit=0)

source code 

Generate help text about this field in HTML format.

'edit' -- If true, display information about editing controls for this field.

Overrides: Field.GetHtmlHelp
(inherited documentation)

FormatValueAsText(self, value, columns=72)

source code 

Return a plain text rendering of a 'value' for this field.

'columns' -- The maximum width of each line of text.

returns -- A plain-text string representing 'value'.

Overrides: Field.FormatValueAsText
(inherited documentation)

FormatValueAsHtml(self, server, value, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

Overrides: Field.FormatValueAsHtml
(inherited documentation)

MakeDomNodeForValue(self, value, document)

source code 

Generate a DOM element node for a value of this field.

'value' -- The value to represent.

'document' -- The containing DOM document node.

Overrides: Field.MakeDomNodeForValue
(inherited documentation)

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

Overrides: Field.Validate
(inherited documentation)

ParseTextValue(self, value)

source code 

Parse a value represented as a string.

'value' -- A string representing the value.

returns -- The corresponding field value. The value returned should be processed by 'Validate' to ensure that it is valid before it is returned.

Overrides: Field.ParseTextValue
(inherited documentation)

ParseFormValue(self, request, name, attachment_stores)

source code 

Convert a value submitted from an HTML form.

'request' -- The 'WebRequest' containing a value corresponding to this field.

'name' -- The name corresponding to this field in the 'request'.

'attachment_stores' -- A dictionary mapping 'AttachmentStore' ids (in the sense of Python's 'id' built-in) to the 'AttachmentStore's themselves.

returns -- A pair '(value, redisplay)'. 'value' is the value for this field, as indicated in 'request'. 'redisplay' is true if and only if the form should be redisplayed, rather than committed. If an error occurs, an exception is thrown.

Overrides: Field.ParseFormValue
(inherited documentation)

GetValueFromDomNode(self, node, attachment_store)

source code 

Return a value for this field represented by DOM 'node'.

This method does not validate the value for this particular instance; it only makes sure the node is well-formed, and returns a value of the correct Python type.

'node' -- The DOM node that is being evaluated.

'attachment_store' -- For attachments, the store that should be used.

If the 'node' is incorrectly formed, this method should raise an exception.

Overrides: Field.GetValueFromDomNode
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.thread_target.ThreadTarget-class.html0000664000076400007640000010671011122067150032205 0ustar stefanstefan qm.test.classes.thread_target.ThreadTarget
Package qm :: Package test :: Package classes :: Module thread_target :: Class ThreadTarget
[hide private]
[frames] | no frames]

Class ThreadTarget

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
          target.Target --+
                          |
                         ThreadTarget

A target implementation that runs tests in local threads.

Each thread executes one test or resource at a time.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, properties)
Construct a 'ThreadTarget'.
source code
 
IsIdle(self)
Return true if the target is idle.
source code
 
Start(self, response_queue, engine=None)
Start the target.
source code
 
Stop(self)
Stop the target.
source code
 
RunTest(self, descriptor, context)
Run the test given by 'descriptor'.
source code
 
_RunTest(self, descriptor, context)
Run the test given by 'descriptor'.
source code
 
_RecordResult(self, result)
Record the 'result'.
source code
 
_BeginResourceSetUp(self, resource_name)
Begin setting up the indicated resource.
source code
 
_FinishResourceSetUp(self, resource, result, properties)
Finish setting up a resource.
source code
 
_NoteIdleThread(self)
Note that the current thread.
source code
 
_Trace(self, message)
Write a trace 'message'.
source code
 
_GetTemporaryDirectory(self)
Return the path to a temporary directory.
source code

Inherited from target.Target: GetDatabase, GetGroup, GetName, IsInGroup

Inherited from target.Target (private): _CleanUpResource, _SetUpResource

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.IntegerField(name= "threads", title= "N...
A list of the arguments to the extension class.

Inherited from target.Target: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, properties)
(Constructor)

source code 

Construct a 'ThreadTarget'.

'database' -- The 'Database' containing the tests that will be run.

'properties' -- A dictionary mapping strings (property names) to strings (property values).

Overrides: object.__init__

IsIdle(self)

source code 

Return true if the target is idle.

returns -- True if the target is idle. If the target is idle, additional tasks may be assigned to it.

Overrides: target.Target.IsIdle

Start(self, response_queue, engine=None)

source code 

Start the target.

'response_queue' -- The 'Queue' in which the results of test executions are placed.

'engine' -- The 'ExecutionEngine' that is starting the target, or 'None' if this target is being started without an 'ExecutionEngine'.

Overrides: target.Target.Start

Stop(self)

source code 

Stop the target.

postconditions -- The target may no longer be used.

Overrides: target.Target.Stop

RunTest(self, descriptor, context)

source code 

Run the test given by 'descriptor'.

'descriptor' -- The 'TestDescriptor' for the test.

'context' -- The 'Context' in which to run the test.

Derived classes may override this method.

Overrides: target.Target.RunTest

_RunTest(self, descriptor, context)

source code 

Run the test given by 'descriptor'.

'descriptor' -- The 'TestDescriptor' for the test.

'context' -- The 'Context' in which to run the test.

This method will be called from the thread that has been assigned the test.

_RecordResult(self, result)

source code 

Record the 'result'.

'result' -- A 'Result' of a test or resource execution.

Overrides: target.Target._RecordResult

_BeginResourceSetUp(self, resource_name)

source code 

Begin setting up the indicated resource.

'resource_name' -- A string naming a resource.

returns -- If the resource has already been set up, returns a tuple '(outcome, map)'. The 'outcome' indicates the outcome that resulted when the resource was set up; the 'map' is a map from strings to strings indicating properties added by this resource. Otherwise, returns 'None', but marks the resource as in the process of being set up; it is the caller's responsibility to finish setting it up by calling '_FinishResourceSetUp'.

Overrides: target.Target._BeginResourceSetUp

_FinishResourceSetUp(self, resource, result, properties)

source code 

Finish setting up a resource.

'resource' -- The 'Resource' itself.

'result' -- The 'Result' associated with setting up the resource.

'properties' -- A dictionary of additional context properties that should be provided to tests that depend on this resource.

returns -- A tuple of the same form as is returned by '_BeginResourceSetUp' when the resource has already been set up.

Overrides: target.Target._FinishResourceSetUp
(inherited documentation)

_NoteIdleThread(self)

source code 

Note that the current thread.

This method is called by the thread when it has completed a task.

_Trace(self, message)

source code 

Write a trace 'message'.

'message' -- A string to be output as a trace message.

_GetTemporaryDirectory(self)

source code 

Return the path to a temporary directory.

returns -- The path to a temporary directory to pass along to tests and resources via the 'TMPDIR_CONTEXT_PROPERTY'.

Overrides: target.Target._GetTemporaryDirectory
(inherited documentation)

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.IntegerField(name= "threads", title= "Number of Threads", d\
escription= """The number of threads to devote to running tests.

            A positive integer that indicates the number of threads to
            use when running tests.  Larger numbers will allow more
            tests to be run at once.  You can experiment with this
            value to find the number that results in the fastest
            execution.""", default_value= 1),]

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-Z.html0000664000076400007640000001362011122067144024320 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

Z



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate-pysrc.html0000664000076400007640000002442311122067162027532 0ustar stefanstefan qm.external.DocumentTemplate
Package qm :: Package external :: Package DocumentTemplate
[hide private]
[frames] | no frames]

Source Code for Package qm.external.DocumentTemplate

 1  ############################################################################## 
 2  # 
 3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
 4  # 
 5  # This software is subject to the provisions of the Zope Public License, 
 6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
 7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
 8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
10  # FOR A PARTICULAR PURPOSE 
11  # 
12  ############################################################################## 
13  __doc__='''Package wrapper for Document Template 
14   
15  This wrapper allows the (now many) document template modules to be 
16  segregated in a separate package. 
17   
18  $Id: __init__.py 40218 2005-11-18 14:39:19Z andreasjung $''' 
19  __version__='$Revision: 1.18 $'[11:-2] 
20   
21  from DocumentTemplate import String, File, HTML, HTMLDefault, HTMLFile 
22   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.file_label-module.html0000664000076400007640000001131111122067145027245 0ustar stefanstefan qm.test.classes.file_label
Package qm :: Package test :: Package classes :: Module file_label
[hide private]
[frames] | no frames]

Module file_label

source code

Classes [hide private]
  FileLabel
A 'FileLabel' is a 'Label' that uses the filesystem's naming scheme.
qmtest-2.4.1/share/doc/qmtest/html/manual/str-class.html0000664000076400007640000021053611122067151022600 0ustar stefanstefan str
str :: Class str
[hide private]
[frames] | no frames]

Class str

object --+    
         |    
basestring --+
             |
            str

str(object) -> string

Return a nice string representation of the object. If the argument is a string, the return value is the same object.

Instance Methods [hide private]
 
__add__(x, y)
x+y
 
__contains__(x, y)
y in x
 
__eq__(x, y)
x==y
 
__ge__(x, y)
x>=y
 
__getattribute__(...)
x.__getattribute__('name') <==> x.name
 
__getitem__(x, y)
x[y]
 
__getnewargs__(...)
 
__getslice__(x, i, j)
x[i:j]
 
__gt__(x, y)
x>y
 
__hash__(x)
hash(x)
 
__le__(x, y)
x<=y
 
__len__(x)
len(x)
 
__lt__(x, y)
x<y
 
__mod__(x, y)
x%y
 
__mul__(x, n)
x*n
 
__ne__(x, y)
x!=y
a new object with type S, a subtype of T
__new__(T, S, ...)
 
__repr__(x)
repr(x)
 
__rmod__(x, y)
y%x
 
__rmul__(x, n)
n*x
 
__str__(x)
str(x)
string
capitalize(S)
Return a copy of the string S with only its first character capitalized.
string
center(S, width, fillchar=...)
Return S centered in a string of length width.
int
count(S, sub, start=..., end=...)
Return the number of non-overlapping occurrences of substring sub in string S[start:end].
object
decode(S, encoding=..., errors=...)
Decodes S using the codec registered for encoding.
object
encode(S, encoding=..., errors=...)
Encodes S using the codec registered for encoding.
bool
endswith(S, suffix, start=..., end=...)
Return True if S ends with the specified suffix, False otherwise.
string
expandtabs(S, tabsize=...)
Return a copy of S where all tab characters are expanded using spaces.
int
find(S, sub, start=... , end=...)
Return the lowest index in S where substring sub is found, such that sub is contained within s[start,end].
int
index(S, sub, start=... , end=...)
Like S.find() but raise ValueError when the substring is not found.
bool
isalnum(S)
Return True if all characters in S are alphanumeric and there is at least one character in S, False otherwise.
bool
isalpha(S)
Return True if all characters in S are alphabetic and there is at least one character in S, False otherwise.
bool
isdigit(S)
Return True if all characters in S are digits and there is at least one character in S, False otherwise.
bool
islower(S)
Return True if all cased characters in S are lowercase and there is at least one cased character in S, False otherwise.
bool
isspace(S)
Return True if all characters in S are whitespace and there is at least one character in S, False otherwise.
bool
istitle(S)
Return True if S is a titlecased string and there is at least one character in S, i.e.
bool
isupper(S)
Return True if all cased characters in S are uppercase and there is at least one cased character in S, False otherwise.
string
join(S, sequence)
Return a string which is the concatenation of the strings in the sequence.
string
ljust(S, width, fillchar=...)
Return S left justified in a string of length width.
string
lower(S)
Return a copy of the string S converted to lowercase.
string or unicode
lstrip(S, chars=...)
Return a copy of the string S with leading whitespace removed.
(head, sep, tail)
partition(S, sep)
Searches for the separator sep in S, and returns the part before it, the separator itself, and the part after it.
 
replace(...)
S.replace (old, new[, count]) -> string
int
rfind(S, sub, start=... , end=...)
Return the highest index in S where substring sub is found, such that sub is contained within s[start,end].
int
rindex(S, sub, start=... , end=...)
Like S.rfind() but raise ValueError when the substring is not found.
string
rjust(S, width, fillchar=...)
Return S right justified in a string of length width.
(tail, sep, head)
rpartition(S, sep)
Searches for the separator sep in S, starting at the end of S, and returns the part before it, the separator itself, and the part after it.
list of strings
rsplit(S, sep=... , maxsplit=...)
Return a list of the words in the string S, using sep as the delimiter string, starting at the end of the string and working to the front.
string or unicode
rstrip(S, chars=...)
Return a copy of the string S with trailing whitespace removed.
list of strings
split(S, sep=... , maxsplit=...)
Return a list of the words in the string S, using sep as the delimiter string.
list of strings
splitlines(S, keepends=...)
Return a list of the lines in S, breaking at line boundaries.
bool
startswith(S, prefix, start=..., end=...)
Return True if S starts with the specified prefix, False otherwise.
string or unicode
strip(S, chars=...)
Return a copy of the string S with leading and trailing whitespace removed.
string
swapcase(S)
Return a copy of the string S with uppercase characters converted to lowercase and vice versa.
string
title(S)
Return a titlecased version of S, i.e.
string
translate(S, table, deletechars=...)
Return a copy of the string S, where all characters occurring in the optional argument deletechars are removed, and the remaining characters have been mapped through the given translation table, which must be a string of length 256.
string
upper(S)
Return a copy of the string S converted to uppercase.
string
zfill(S, width)
Pad a numeric string S with zeros on the left, to fill a field of the specified width.

Inherited from object: __delattr__, __init__, __reduce__, __reduce_ex__, __setattr__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__getattribute__(...)

 

x.__getattribute__('name') <==> x.name

Overrides: object.__getattribute__

__getslice__(x, i, j)
(Slicling operator)

 

x[i:j]

Use of negative indices is not supported.

__hash__(x)
(Hashing function)

 

hash(x)

Overrides: object.__hash__

__new__(T, S, ...)

 
Returns: a new object with type S, a subtype of T
Overrides: object.__new__

__repr__(x)
(Representation operator)

 

repr(x)

Overrides: object.__repr__

__str__(x)
(Informal representation operator)

 

str(x)

Overrides: object.__str__

center(S, width, fillchar=...)

 

Return S centered in a string of length width. Padding is done using the specified fill character (default is a space)

Returns: string

count(S, sub, start=..., end=...)

 

Return the number of non-overlapping occurrences of substring sub in string S[start:end]. Optional arguments start and end are interpreted as in slice notation.

Returns: int

decode(S, encoding=..., errors=...)

 

Decodes S using the codec registered for encoding. encoding defaults to the default encoding. errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors raise a UnicodeDecodeError. Other possible values are 'ignore' and 'replace' as well as any other name registerd with codecs.register_error that is able to handle UnicodeDecodeErrors.

Returns: object

encode(S, encoding=..., errors=...)

 

Encodes S using the codec registered for encoding. encoding defaults to the default encoding. errors may be given to set a different error handling scheme. Default is 'strict' meaning that encoding errors raise a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and 'xmlcharrefreplace' as well as any other name registered with codecs.register_error that is able to handle UnicodeEncodeErrors.

Returns: object

endswith(S, suffix, start=..., end=...)

 

Return True if S ends with the specified suffix, False otherwise. With optional start, test S beginning at that position. With optional end, stop comparing S at that position. suffix can also be a tuple of strings to try.

Returns: bool

expandtabs(S, tabsize=...)

 

Return a copy of S where all tab characters are expanded using spaces. If tabsize is not given, a tab size of 8 characters is assumed.

Returns: string

find(S, sub, start=... , end=...)

 

Return the lowest index in S where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation.

Return -1 on failure.

Returns: int

istitle(S)

 

Return True if S is a titlecased string and there is at least one character in S, i.e. uppercase characters may only follow uncased characters and lowercase characters only cased ones. Return False otherwise.

Returns: bool

join(S, sequence)

 

Return a string which is the concatenation of the strings in the sequence. The separator between elements is S.

Returns: string

ljust(S, width, fillchar=...)

 

Return S left justified in a string of length width. Padding is done using the specified fill character (default is a space).

Returns: string

lstrip(S, chars=...)

 

Return a copy of the string S with leading whitespace removed. If chars is given and not None, remove characters in chars instead. If chars is unicode, S will be converted to unicode before stripping

Returns: string or unicode

partition(S, sep)

 

Searches for the separator sep in S, and returns the part before it, the separator itself, and the part after it. If the separator is not found, returns S and two empty strings.

Returns: (head, sep, tail)

replace(...)

 

S.replace (old, new[, count]) -> string

Return a copy of string S with all occurrences of substring old replaced by new. If the optional argument count is given, only the first count occurrences are replaced.

rfind(S, sub, start=... , end=...)

 

Return the highest index in S where substring sub is found, such that sub is contained within s[start,end]. Optional arguments start and end are interpreted as in slice notation.

Return -1 on failure.

Returns: int

rjust(S, width, fillchar=...)

 

Return S right justified in a string of length width. Padding is done using the specified fill character (default is a space)

Returns: string

rpartition(S, sep)

 

Searches for the separator sep in S, starting at the end of S, and returns the part before it, the separator itself, and the part after it. If the separator is not found, returns two empty strings and S.

Returns: (tail, sep, head)

rsplit(S, sep=... , maxsplit=...)

 

Return a list of the words in the string S, using sep as the delimiter string, starting at the end of the string and working to the front. If maxsplit is given, at most maxsplit splits are done. If sep is not specified or is None, any whitespace string is a separator.

Returns: list of strings

rstrip(S, chars=...)

 

Return a copy of the string S with trailing whitespace removed. If chars is given and not None, remove characters in chars instead. If chars is unicode, S will be converted to unicode before stripping

Returns: string or unicode

split(S, sep=... , maxsplit=...)

 

Return a list of the words in the string S, using sep as the delimiter string. If maxsplit is given, at most maxsplit splits are done. If sep is not specified or is None, any whitespace string is a separator.

Returns: list of strings

splitlines(S, keepends=...)

 

Return a list of the lines in S, breaking at line boundaries. Line breaks are not included in the resulting list unless keepends is given and true.

Returns: list of strings

startswith(S, prefix, start=..., end=...)

 

Return True if S starts with the specified prefix, False otherwise. With optional start, test S beginning at that position. With optional end, stop comparing S at that position. prefix can also be a tuple of strings to try.

Returns: bool

strip(S, chars=...)

 

Return a copy of the string S with leading and trailing whitespace removed. If chars is given and not None, remove characters in chars instead. If chars is unicode, S will be converted to unicode before stripping

Returns: string or unicode

title(S)

 

Return a titlecased version of S, i.e. words start with uppercase characters, all remaining cased characters have lowercase.

Returns: string

zfill(S, width)

 

Pad a numeric string S with zeros on the left, to fill a field of the specified width. The string S is never truncated.

Returns: string

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python.ExceptionTest-class.html0000664000076400007640000004643111122067147031142 0ustar stefanstefan qm.test.classes.python.ExceptionTest
Package qm :: Package test :: Package classes :: Module python :: Class ExceptionTest
[hide private]
[frames] | no frames]

Class ExceptionTest

source code

         object --+                
                  |                
extension.Extension --+            
                      |            
      runnable.Runnable --+        
                          |        
                  test.Test --+    
                              |    
              BaseExceptionTest --+
                                  |
                                 ExceptionTest

Check that the specified Python code raises an exception.

An 'ExceptionTest' checks that the specified Python code raises a particular exception. The test passes if the exception is an instance of the expected class and (optionally) if its value matches the expected value. If the code fails to raise an exception, the test fails.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
MakeResult(self, exc_info, result)
Check the exception in 'exc_info' and construct the result.
source code
 
CheckArgument(self, exc_info, result)
Check that the exception argument matches expectations.
source code

Inherited from BaseExceptionTest: Run

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "exception_class", titl...
A list of the arguments to the extension class.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

MakeResult(self, exc_info, result)

source code 

Check the exception in 'exc_info' and construct the result.

'result' -- The result object for this test.

Overrides: BaseExceptionTest.MakeResult
(inherited documentation)

CheckArgument(self, exc_info, result)

source code 

Check that the exception argument matches expectations.

'result' -- The result object for this test.

Overrides: BaseExceptionTest.CheckArgument

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "exception_class", title= "Exception Class"\
, description= """The expected type of the exception.

            This value is the name of a Python class.  If the
            exception raised is not an instance of this class, the
            test fails.""", default_value= "Exception")]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.temporary_directory-pysrc.html0000664000076400007640000006120711122067154026547 0ustar stefanstefan qm.temporary_directory
Package qm :: Module temporary_directory
[hide private]
[frames] | no frames]

Source Code for Module qm.temporary_directory

 1  ######################################################################## 
 2  # 
 3  # File:   temporary_directory.py 
 4  # Author: Mark Mitchell 
 5  # Date:   05/07/2003 
 6  # 
 7  # Contents: 
 8  #   TemporaryDirectory 
 9  # 
10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ######################################################################## 
17   
18  import dircache 
19  import os 
20  import qm 
21  import sys 
22  import tempfile 
23   
24  ######################################################################## 
25  # Classes 
26  ######################################################################## 
27   
29 """A 'TemporaryDirectory' is a directory for temporary files. 30 31 Creating a new 'TemporaryDirectory results in the creation of a 32 new directory in the file system. The directory is automatically 33 removed from the file system when the 'TemporaryDirectory' is 34 destroyed.""" 35
36 - def __init__(self):
37 """Construct a new 'TemporaryDirectory.""" 38 39 self.__directory = None 40 41 dir_path = tempfile.mktemp() 42 try: 43 os.mkdir(dir_path, 0700) 44 except: 45 exc_info = sys.exc_info() 46 raise qm.common.QMException, \ 47 qm.error("temp dir error", 48 dir_path=dir_path, 49 exc_class=str(exc_info[0]), 50 exc_arg=str(exc_info[1])) 51 52 self.__directory = dir_path
53 54
55 - def GetPath(self):
56 """Returns the path to the temporary directory. 57 58 returns -- The path to the temporary directory.""" 59 60 return self.__directory
61 62
63 - def __del__(self):
64 65 self.Remove()
66 67
68 - def Remove(self):
69 """Remove the temporary directory. 70 71 Removes the temporary directory, and all files and directories 72 contained within it, from the file system.""" 73 74 if self.__directory is not None: 75 self.__RemoveDirectory(self.__directory) 76 self.__directory = None
77 78
79 - def __RemoveDirectory(self, path):
80 """Remove the directory 'path'. 81 82 Removes 'path', after first removing all of its contents.""" 83 84 # Remove everything in the directory. 85 for entry in dircache.listdir(path): 86 entry_path = os.path.join(path, entry) 87 if os.path.isdir(entry_path): 88 self.__RemoveDirectory(entry_path) 89 else: 90 os.unlink(entry_path) 91 # Remove the directory itself. 92 os.rmdir(path)
93

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-R.html0000664000076400007640000010664411122067144024321 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

R



qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.web.web-module.html0000664000076400007640000000577011122067144025662 0ustar stefanstefan web

Module web


Classes

ContextPage
DefaultDtmlPage
DirPage
DirReportPage
Item
LoadContextPage
LoadExpectationsPage
LoadResultsPage
NewItemPage
NewSuitePage
QMTestPage
QMTestReportPage
QMTestServer
ResultPage
SetExpectationPage
ShowItemPage
ShowItemReportPage
ShowSuitePage
StorageResultsStream
TestResultsPage

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.resource_adapter-module.html0000664000076400007640000000215411122067144027651 0ustar stefanstefan resource_adapter

Module resource_adapter


Classes

ResourceAdapter

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.StorageResultsStream-class.html0000664000076400007640000007075411122067151031062 0ustar stefanstefan qm.test.web.web.StorageResultsStream
Package qm :: Package test :: Package web :: Module web :: Class StorageResultsStream
[hide private]
[frames] | no frames]

Class StorageResultsStream

source code

            object --+        
                     |        
   extension.Extension --+    
                         |    
result_stream.ResultStream --+
                             |
                            StorageResultsStream

A 'StorageResultsStream' stores results.

A 'StorageResultsStream' does not write any output. It simply stores the results for future display.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self)
Construct a 'StorageResultsStream'.
source code
 
GetAnnotations(self)
Return the annotations for this run.
source code
 
WriteAnnotation(self, key, value)
Output an annotation for this run.
source code
 
WriteResult(self, result)
Output a test result.
source code
 
Summarize(self)
Output summary information about the results.
source code
 
Start(self, test_ids)
Start collecting results.
source code
 
IsFinished(self)
Return true iff no more results are forthcoming.
source code
 
GetTestResults(self)
Return the accumulated test results.
source code
 
GetTestResultsInOrder(self)
Return the test results in the order they appeared.
source code
 
GetResourceResults(self)
Return the accumulated resource results.
source code
 
GetResult(self, name)
Return the 'Result' with the indicated 'name'.
source code

Inherited from result_stream.ResultStream: WriteAllAnnotations

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from result_stream.ResultStream: expected_outcomes, kind

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self)
(Constructor)

source code 

Construct a 'StorageResultsStream'.

Overrides: object.__init__

WriteAnnotation(self, key, value)

source code 

Output an annotation for this run.

Subclasses should override this if they want to store/display annotations; the default implementation simply discards them.

'key' -- the key value as a string.

'value' -- the value of this annotation as a string.

Overrides: result_stream.ResultStream.WriteAnnotation
(inherited documentation)

WriteResult(self, result)

source code 

Output a test result.

'result' -- A 'Result'.

Overrides: result_stream.ResultStream.WriteResult

Summarize(self)

source code 

Output summary information about the results.

When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point.

Derived class methods may override this method. They should, however, invoke this version before returning.

Overrides: result_stream.ResultStream.Summarize

Start(self, test_ids)

source code 

Start collecting results.

'test_ids' -- The names of the tests that we are about to run.

Start collecting new results. Discard results for the 'test_ids', but not for other tests.

IsFinished(self)

source code 

Return true iff no more results are forthcoming.

returns -- True if no more results will be written to this stream.

GetTestResults(self)

source code 

Return the accumulated test results.

returns -- A dictionary mapping test names to 'Result' objects.

GetTestResultsInOrder(self)

source code 

Return the test results in the order they appeared.

returns -- A sequence of test results, in the order that they appeared.

GetResourceResults(self)

source code 

Return the accumulated resource results.

returns -- A dictionary mapping resource names to 'Result' objects.

GetResult(self, name)

source code 

Return the 'Result' with the indicated 'name'.

'name' -- A string giving the name of a test or resource result.

returns -- The 'Result' instance corresponding to 'name'.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_result_reader-pysrc.html0000664000076400007640000017054711122067152027264 0ustar stefanstefan qm.test.file_result_reader
Package qm :: Package test :: Module file_result_reader
[hide private]
[frames] | no frames]

Source Code for Module qm.test.file_result_reader

 1  ######################################################################## 
 2  # 
 3  # File:   file_result_reader.py 
 4  # Author: Nathaniel Smith 
 5  # Date:   2003-06-23 
 6  # 
 7  # Contents: 
 8  #   FileResultReader 
 9  # 
10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from qm.fields import TextField, PythonField 
21  from qm.common import QMException 
22  from qm.test.result_reader import ResultReader 
23  import sys 
24   
25  ######################################################################## 
26  # Classes 
27  ######################################################################## 
28   
29 -class FileResultReader(ResultReader):
30 """A 'FileResultReader' gets its input from a file. 31 32 A 'FileResultReader' is an abstract base class for other result 33 reader classes that read results from a single file. The file 34 from which results should be read can be specified using either 35 the 'filename' argument or the 'file' argument. The latter is for 36 use by QMTest internally.""" 37
38 - class InvalidFile(QMException):
39 """An 'InvalidFile' exception indicates an incorrect file format. 40 41 If the constructor for a 'FileResultStream' detects an invalid 42 file, it must raise an instance of this exception.""" 43 44 pass
45 46 47 48 arguments = [ 49 TextField( 50 name = "filename", 51 title = "File Name", 52 description = """The name of the file. 53 54 All results will be read from the file indicated. If no 55 filename is specified, or the filename specified is "-", 56 the standard input will be used.""", 57 verbatim = "true", 58 default_value = ""), 59 PythonField( 60 name = "file"), 61 ] 62 63 _is_binary_file = 0 64 """If true, results are stored in a binary format. 65 66 This flag can be overridden by derived classes.""" 67
68 - def __init__(self, arguments = None, **args):
69 """Construct a new 'FileResultReader'. 70 71 'arguments' -- As for 'ResultReader'. 72 73 If the file provided is not in the input format expected by this 74 result reader, the derived class '__init__' function must raise 75 an 'InvalidStream' exception.""" 76 77 super(FileResultReader, self).__init__(arguments, **args) 78 79 if not self.file: 80 if self.filename and self.filename != "-": 81 if self._is_binary_file: 82 mode = "rb" 83 else: 84 mode = "r" 85 self.file = open(self.filename, mode, 0) 86 else: 87 self.file = sys.stdin
88 89 90 ######################################################################## 91 # Local Variables: 92 # mode: python 93 # indent-tabs-mode: nil 94 # fill-column: 72 95 # End: 96

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.temporary-module.html0000664000076400007640000001127511122067145027222 0ustar stefanstefan qm.test.classes.temporary
Package qm :: Package test :: Package classes :: Module temporary
[hide private]
[frames] | no frames]

Module temporary

source code

Classes [hide private]
  TempDirectoryResource
Resource class to manage a temporary directory.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.file-pysrc.html0000664000076400007640000023307611122067160025774 0ustar stefanstefan qm.test.classes.file
Package qm :: Package test :: Package classes :: Module file
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.file

  1  ######################################################################## 
  2  # 
  3  # File:   file.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-06-21 
  6  # 
  7  # Contents: 
  8  #   Test classes involving file contents. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  """File-related test classes.""" 
 17   
 18  ######################################################################## 
 19  # imports 
 20  ######################################################################## 
 21   
 22  import qm.fields 
 23  import qm.test.base 
 24  from   qm.test.result import * 
 25  from   qm.test.test import * 
 26  import qm.web 
 27  import re 
 28  import string 
 29   
 30  ######################################################################## 
 31  # classes 
 32  ######################################################################## 
 33   
34 -class SubstitutionField(qm.fields.TupleField):
35 """A rule for performing a text substitution. 36 37 A 'SubstitutionField' consists of a regular expression pattern and a 38 corresponding replacement string. When the substitution is applied 39 to a body of text, all substrings that match the pattern are 40 replaced with the substitution string. 41 42 The syntax for the regular expression and the substitution string is 43 that of the standard Python 're' (regular expression) module.""" 44
45 - def __init__(self, name, **properties):
46 """Create a new 'SubstitutionField'. 47 48 By default, the pattern and replacement string are empty.""" 49 50 # Initialize the base class. 51 fields = (qm.fields.TextField(name = "pattern", 52 title = "Pattern",), 53 qm.fields.TextField(name = "replacement", 54 title = "Replacement")) 55 qm.fields.TupleField.__init__(self, name, fields, **properties)
56 57
58 - def GetHelp(self):
59 return """ 60 A substitution consists of a regular expression pattern and a 61 substitution string. When the substitution is applied, all 62 subtrings matching the pattern are replaced with the 63 substitution string. The substitution string may reference 64 matched groups in the pattern. 65 66 The regular expression and substitution syntax are those of 67 Python's standard "'re' regular expression module"."""
68 69 70
71 -class FileContentsTest(Test):
72 """Check that the contents of a file match the expected value. 73 74 A 'FileContentsTest' examines the contents of a file. The test 75 passes if and only if the contents exactly match the expected value. 76 77 The path to the file itself is not specified explicitly in the test. 78 Instead, it is taken from a contex property; the name of that 79 variable is specified in the **Path Property** field. 80 81 Optionally, the test may specify one or more substitutions. Each 82 substitution consists of a regular expression pattern and a 83 replacement string. Both the actual file contents and the expected 84 file contents are processed with these substitutions, with all 85 pattern matches replaced with the corresponding substitutions, 86 before the comparison is performed.""" 87 88 arguments = [ 89 qm.fields.TextField( 90 name="path_property", 91 title="Path Property", 92 description="""The context property naming the file. 93 94 The context property given here will contain the path name 95 of the file.""", 96 not_empty_text=1, 97 default_value="path"), 98 99 qm.fields.TextField( 100 name="expected_contents", 101 title="Expected Contents", 102 description="""The expected contents of the file.""", 103 verbatim="true", 104 multiline="true", 105 default_value=""), 106 107 qm.fields.SetField(SubstitutionField( 108 name="substitutions", 109 title="Substitutions", 110 description="""Regular expression substitutions. 111 112 Each substitution will be applied to both the expected and 113 actual contents of the file. The comparison will be 114 performed after the substitutions have been performed. 115 116 You can use substitutions to ignore insignificant 117 differences between the expected and autual contents.""")) 118 ] 119 120
121 - def Run(self, context, result):
122 # Extract the path to the file we're testing. 123 path = context[self.path_property] 124 # Read the contents of the file. 125 contents = open(path, "r").read() 126 # Perform substitutions on the file contents. 127 self.expected_contents = \ 128 self.__PerformSubstitutions(self.expected_contents) 129 contents = self.__PerformSubstitutions(contents) 130 # Compare the contents to the expected contents. 131 if contents != self.expected_contents: 132 result.Fail("Contents do not match expected contents.", 133 { "FileContentsTest.contents" : contents, 134 "FileContentsTest.expected_contents" : 135 self.expected_contents })
136 137
138 - def __PerformSubstitutions(self, text):
139 """Perform substitutions on a body of text. 140 141 returns -- The string 'text', processed with the substitutions 142 configured for this test instance.""" 143 144 for pattern, replacement in self.substitutions: 145 text = re.sub(pattern, replacement, text) 146 return text
147 148 149 150 ######################################################################## 151 # Local Variables: 152 # mode: python 153 # indent-tabs-mode: nil 154 # fill-column: 72 155 # End: 156

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.mount_database.MountDatabase-class.html0000664000076400007640000012122311122067147032531 0ustar stefanstefan qm.test.classes.mount_database.MountDatabase
Package qm :: Package test :: Package classes :: Module mount_database :: Class MountDatabase
[hide private]
[frames] | no frames]

Class MountDatabase

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
      database.Database --+
                          |
                         MountDatabase

A 'MountDatabase' contains other databases.

Every contained database has a "mount point", which is a label giving the root of the database. A test with the ID "x" in a database with a mount point of "y" has the ID "x.y" in the containing database.

The contained databases are found by looking for subdirectories of the 'MountDatabase' directory. Every immediate subdirectory which is itself a QMTest database is mounted; its mount point is the name of the subdirectory.

Nested Classes [hide private]
  MountedSuite
A 'MountedSuite' is a suite from a mounted database.

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, path, arguments)
Construct a 'Database'.
source code
 
GetIds(self, kind, directory='', scan_subdirs=1)
Return all IDs of the indicated 'kind' that begin with 'directory'.
source code
 
GetTest(self, test_id)
Return the 'TestDescriptor' for the test named 'test_id'.
source code
 
GetResource(self, resource_id)
Return the 'ResourceDescriptor' for the resource 'resouce_id'.
source code
 
GetSuite(self, suite_id)
Return the 'Suite' for the suite named 'suite_id'.
source code
 
GetSubdirectories(self, directory)
Return the immediate subdirectories of 'directory'.
source code
 
GetClassPaths(self)
Return directories to search for test and resource classes.
source code
 
_AdjustResources(self, joiner, arguments)
Adjust the resource IDs stored in the 'arguments'.
source code
 
_GetContainedItem(self, kind, item_id)
Return 'item_id' from a mounted database.
source code
 
_SelectDatabase(self, item_id)
Return the contained database in which 'item_id' can be found.
source code

Inherited from database.Database: ExpandIds, GetAttachmentStore, GetConfigurationDirectory, GetExtension, GetExtensions, GetItem, GetLabelComponents, GetPath, GetResourceClassNames, GetResourceIds, GetSuiteIds, GetTestClassNames, GetTestIds, HasResource, HasSuite, HasTest, IsModifiable, IsValidLabel, JoinLabels, RemoveExtension, SplitLabel, SplitLabelLeft, WriteExtension

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  mounts = None
  _argument_dictionary = {'label_class': <<class 'qm.fields.Text...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.DictionaryField'> mounts>...
A list of all the 'Field's in this class.

Inherited from database.Database: ITEM_KINDS, RESOURCE, SUITE, TEST, arguments, kind, label_class, modifiable

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, path, arguments)
(Constructor)

source code 

Construct a 'Database'.

'path' -- A string containing the absolute path to the directory containing the database.

'arguments' -- A dictionary mapping attribute names to values. The use of this parameter is deprecated. Use keyword arguments instead.

Derived classes must call this method from their own '__init__' methods. Every derived class must have an '__init__' method that takes the path to the directory containing the database as its only argument. The path provided to the derived class '__init__' function will always be an absolute path.

Overrides: object.__init__
(inherited documentation)

GetIds(self, kind, directory='', scan_subdirs=1)

source code 

Return all IDs of the indicated 'kind' that begin with 'directory'.

'kind' -- One of the 'ITEM_KINDS'.

'directory' -- A label indicating the directory in which to begin the search.

'scan_subdirs' -- True if (and only if) subdirectories of 'directory' should be scanned.

returns -- A list of all items of the indicated 'kind' located within 'directory', as absolute labels.

Derived classes may override this method.

Overrides: database.Database.GetIds
(inherited documentation)

GetTest(self, test_id)

source code 

Return the 'TestDescriptor' for the test named 'test_id'.

'test_id' -- A label naming the test.

returns -- A 'TestDescriptor' corresponding to 'test_id'.

raises -- 'NoSuchTestError' if there is no test in the database named 'test_id'.

Overrides: database.Database.GetTest
(inherited documentation)

GetResource(self, resource_id)

source code 

Return the 'ResourceDescriptor' for the resource 'resouce_id'.

'resource_id' -- A label naming the resource.

returns -- A 'ResourceDescriptor' corresponding to 'resource_id'.

raises -- 'NoSuchResourceError' if there is no resource in the database named 'resource_id'.

Overrides: database.Database.GetResource
(inherited documentation)

GetSuite(self, suite_id)

source code 

Return the 'Suite' for the suite named 'suite_id'.

'suite_id' -- A label naming the suite.

returns -- An instance of 'Suite' (or a derived class of 'Suite') corresponding to 'suite_id'.

raises -- 'NoSuchSuiteError' if there is no test in the database named 'test_id'.

All databases must have an implicit suite called '' that contains all tests in the database. More generally, for each directory in the database, there must be a corresponding suite that contains all tests in that directory and its subdirectories.

Overrides: database.Database.GetSuite
(inherited documentation)

GetSubdirectories(self, directory)

source code 

Return the immediate subdirectories of 'directory'.

'directory' -- A label indicating a directory in the database.

returns -- A sequence of (relative) labels indictating the immediate subdirectories of 'directory'. For example, if "a.b" and "a.c" are directories in the database, this method will return "b" and "c" given "a" as 'directory'.

Derived classes may override this method.

Overrides: database.Database.GetSubdirectories
(inherited documentation)

GetClassPaths(self)

source code 

Return directories to search for test and resource classes.

returns -- A sequence of strings. Each string is a directory that should be searched to locate test and resource classes. The directories will be searched in the order they appear. QMTest will search other directories (like those in the 'QMTEST_CLASS_PATH' environment variable) in addition to these directories.

For a given database, this method should always return the same value; callers are permitted to cache the value returned.

Derived classes may override this method. The sequence returned by the derived class need not be a superset of the value returned by the default implementation (but probably should be).

Overrides: database.Database.GetClassPaths
(inherited documentation)

_AdjustResources(self, joiner, arguments)

source code 

Adjust the resource IDs stored in the 'arguments'.

'joiner' -- A function of one argument which prepends the label for a mount point to the label it is given.

'arguments' -- The arguments to a test or resource class.

Modifies the arguments to contain resource names that are relative to the containing database.

_GetContainedItem(self, kind, item_id)

source code 

Return 'item_id' from a mounted database.

'kind' -- The kind of item to return.

'item_id' -- The name of the item, in the containing database.

returns -- A tuple '(joiner, item). The 'item' will be from one of the mounted databases. 'joiner' is a function of one argument which prepends the mount point to its argument.

_SelectDatabase(self, item_id)

source code 

Return the contained database in which 'item_id' can be found.

'item_id' -- The name of an item in this database.

returns -- A tuple '(database, joiner, id)' where 'database' is a 'Database', 'joiner' is a function of one argument which prepends the mount point to a label, and 'id' is the portion of 'item_id' that remains after stripping off the mount point of 'database'. If 'item_id' does not correspond to any mount point, an exception is raised.


Class Variable Details [hide private]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'label_class': <<class 'qm.fields.TextField'> label_class>,
 'modifiable': <<class 'qm.fields.BooleanField'> modifiable>,
 'mounts': <<class 'qm.fields.DictionaryField'> mounts>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.DictionaryField'> mounts>,
 <<class 'qm.fields.TextField'> label_class>,
 <<class 'qm.fields.BooleanField'> modifiable>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.AccountDisabledError-class.html0000664000076400007640000001500611122067151027412 0ustar stefanstefan qm.user.AccountDisabledError
qm :: user :: AccountDisabledError :: Class AccountDisabledError
[hide private]
[frames] | no frames]

Class AccountDisabledError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
             AuthenticationError --+
                                   |
                                  AccountDisabledError

Instance Methods [hide private]

Inherited from exceptions.Exception: __init__, __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.test-module.html0000664000076400007640000000304611122067144025302 0ustar stefanstefan test

Module test


Classes

TargetGroupField
Test

Functions

get_targets
set_targets

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_stream.DejaGNUReader-class.html0000664000076400007640000007160011122067147032347 0ustar stefanstefan qm.test.classes.dejagnu_stream.DejaGNUReader
Package qm :: Package test :: Package classes :: Module dejagnu_stream :: Class DejaGNUReader
[hide private]
[frames] | no frames]

Class DejaGNUReader

source code

                 object --+            
                          |            
        extension.Extension --+        
                              |        
     result_reader.ResultReader --+    
                                  |    
file_result_reader.FileResultReader --+
                                      |
                                     DejaGNUReader

A 'DejaGNUReader' reads a DejaGNU log file.

The DejaGNU log file may then be processed by QMTest. For example, QMTest may generate results in an alternative format, or display them in the QMTest GUI. Therefore, this reader may be used to obtain the benefits of QMTest's reporting characteristics, when using a legacy DejaGNU testsuite.

Unfortunately, DejaGNU log files are relativley unstructured. Therefore, this result reader uses heuristics that may not always be 100% robust. Therefore, for optimal behavior, DejaGNU testsuites should be converted to QMTest testsuites.

Nested Classes [hide private]

Inherited from file_result_reader.FileResultReader: InvalidFile

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'FileResultReader'.
source code
 
GetResult(self)
Return the next 'Result' from this reader.
source code
 
__NextOutcome(self)
The next DejaGNU outcome in the file.
source code
 
__UpdateResult(self, result, dejagnu_outcome, cause)
Update 'result' as indicated.
source code
 
__UseCombinedMode(self)
Returns true in the combined mode.
source code
 
__GenerateExpectations(self)
Returns true if expected results should be generated.
source code

Inherited from result_reader.ResultReader: GetAnnotations, __iter__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.BooleanField(name= "is_combined", title...
A list of the arguments to the extension class.
  __id_regexp = re.compile("^[^:]*:[\\s]*(?P<id>[^\\s]*)")
A regular expression for determining test names.
  __cause_regexp = re.compile("\\((?P<cause>.*)\\)\\s*$")
A regular expression for determining failure causes.

Inherited from file_result_reader.FileResultReader: file, filename

Inherited from result_reader.ResultReader: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'FileResultReader'.

'arguments' -- As for 'ResultReader'.

If the file provided is not in the input format expected by this result reader, the derived class '__init__' function must raise an 'InvalidStream' exception.

Overrides: object.__init__
(inherited documentation)

GetResult(self)

source code 

Return the next 'Result' from this reader.

returns -- A 'Result', or 'None' if there are no more results.

Overrides: result_reader.ResultReader.GetResult
(inherited documentation)

__NextOutcome(self)

source code 

The next DejaGNU outcome in the file.

returns -- A triplet ('test_id', 'outcome', 'cause'). The 'test_id' is the name of the test. The 'outcome' is the DejaGNU outcome (one of the 'DejaGNUTest.dejagnu_outcomes'). The 'cause' is a string giving the cause (if known) of failure, if the test did not pass.

__UpdateResult(self, result, dejagnu_outcome, cause)

source code 

Update 'result' as indicated.

'result' -- A 'Result', which may contain information from previous DejaGNU tests, in the combined mode.

'dejagnu_outcome' -- The DejaGNU outcome (one of the 'DejaGNUTest.dejagnu_outcomes') that applies to this 'result'.

'cause' -- The cause of failure, if known.

The 'result' is modified to reflect the new outcome and cause. Results can only get worse, in the sense that if reuslt has an outcome of 'Result.FAIL' upon entry to this return, it will never have an outcome of 'Result.PASS' upon return.

__UseCombinedMode(self)

source code 

Returns true in the combined mode.

returns -- True iff results should be read in the combined mode.

__GenerateExpectations(self)

source code 

Returns true if expected results should be generated.

returns -- True iff the results generated should reflect expectations, rather than actual results.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.BooleanField(name= "is_combined", title= "Combined Format?"\
, description= """True if multiple results for the same test should be\
 combined.

            DejaGNU will sometimes print multiple results for the same
            test.  For example, when testing a compiler, DejaGNU may
            issue one result indicating whether or not a file was
            successfully compiled and another result indicating
...

__id_regexp

A regular expression for determining test names.

When applied to an outcome line from DejaGNU, this regular expression's 'id' field gives the name of the test, in the combined mode.

Value:
re.compile("^[^:]*:[\\s]*(?P<id>[^\\s]*)")

__cause_regexp

A regular expression for determining failure causes.

When applied to an outcome line from DejaGNU, this regular expression's 'cause' field gives the cause of the failure.

Value:
re.compile("\\((?P<cause>.*)\\)\\s*$")

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.mount_database-module.html0000664000076400007640000000215211122067144030742 0ustar stefanstefan mount_database

Module mount_database


Classes

MountDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.run_database-pysrc.html0000664000076400007640000016046211122067154026052 0ustar stefanstefan qm.test.run_database
Package qm :: Package test :: Module run_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.run_database

  1  ######################################################################## 
  2  # 
  3  # File:   run_database.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2005-08-08 
  6  # 
  7  # Contents: 
  8  #   QMTest RunDatabase class. 
  9  # 
 10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  from qm.extension import Extension 
 21  from qm.test.result import Result 
 22  from qm.common import parse_time_iso 
 23   
 24  ######################################################################## 
 25  # Classes 
 26  ######################################################################## 
 27   
28 -class RunDatabase(Extension):
29 """A 'RunDatabase' stores 'TestRun's. 30 31 A 'RunDatabase' provides a mechanism for selecting 'TestRun's that 32 meet particular criteria.""" 33
34 - def GetAllRuns(self):
35 """Return all the 'TestRun's in the database. 36 37 returns -- A sequence consisting of all of the 'TestRun's in 38 the database.""" 39 40 raise NotImplementedError
41 42
43 - def GetRuns(self, predicate):
44 """Return the set of 'TestRun's satisfying 'predicate' 45 46 'predicate' -- A callable that can be passed one 'TestRun' 47 argument. 48 49 returns -- A sequence of 'TestRun's consisting only of those 50 'TestRun's in the database for which 'predicate' returns a 51 true value.""" 52 53 return filter(self.GetAllRuns(), predicate)
54 55
56 - def GetAnnotations(self, key):
57 """Return the set of annotations for 'key' from all test runs. 58 59 'key' -- A string used to look up the annotations. 60 61 returns -- A set of (distinct) annotations for 'key' from all 62 test runs.""" 63 64 # We can't use sets since we want to remain python 2.2 compatible. 65 annotations = [] 66 for r in self.GetAllRuns(): 67 value = r.GetAnnotation(key) 68 if value not in annotations: 69 annotations.append(value) 70 return annotations
71 72
73 - def GetTimeframe(self, time_key, is_iso_time = True):
74 """Return a pair of min / max values found for the given time_key 75 across all test runs. 76 77 'time_key' -- Annotation key referring to a string convertible to 78 either iso-formatted time or floating point number. 79 80 returns -- minimum, maximum.""" 81 82 minimum = None 83 maximum = None 84 for r in self.GetAllRuns(): 85 time_string = r.GetAnnotation(time_key) 86 if not time_string: 87 continue 88 if is_iso_time: 89 time = parse_time_iso(time_string) 90 else: 91 time = float(time_string) 92 if not minimum or minimum > time: 93 minimum = time 94 if not maximum or maximum < time: 95 # Make sure the largest value is still inside the interval. 96 maximum = time + 0.1 97 return minimum, maximum
98 99
100 - def GetRunInTimeframe(self, key, value, time_key, minimum, maximum, is_iso_time = True):
101 """Return a test run id matching the key and timeframe.""" 102 103 for i in range(len(self.GetAllRuns())): 104 r = self.GetAllRuns()[i] 105 if r.GetAnnotation(key) != value: 106 continue 107 time_string = r.GetAnnotation(time_key) 108 if not time_string: 109 continue 110 if is_iso_time: 111 time = parse_time_iso(time_string) 112 else: 113 time = float(time_string) 114 if time >= minimum and time < maximum: 115 return i 116 # No match. 117 return None
118 119
120 - def GetRunsByAnnotations(self, annotation_filter):
121 """Return the 'TestRun's matching 'annotation_filter'. 122 123 'annotation_filter' -- A dictionary mapping annotation keys 124 (strings) to values (either strings or callables). 125 126 returns -- A sequence of 'TestRun's consisting only of those 127 'TestRun's in the database that match the 128 'annotation_filter'. A 'TestRun' matches the 129 'annotation_filter' if it matches each of the key-value pairs 130 in the filter. If the value in such a pair is a string, then 131 the annotation in the 'TestRun' must exactly match the value. 132 If the value is a callable, rather than a string, then when 133 passed the value from the 'TestRun', the predicate must return 134 a true value.""" 135 136 def predicate(run): 137 for key, pattern in annotation_filter.iteritems(): 138 value = run.GetAnnotation(key) 139 if callable(pattern): 140 if not pattern(value): 141 return False 142 elif value != pattern: 143 return False 144 return True
145 146 return self.GetRuns(predicate)
147 148
149 - def GetOutcomes(self, id, kind = Result.TEST):
150 """Return an outcome dictionary for the indicated test. 151 152 'id' -- The name of a test, suite, or resource item. 153 154 'kind' -- The kind of the item to retrieve the outcome for. 155 156 returns -- A dictionary indicating the number of outcomes per category.""" 157 158 outcomes = {Result.PASS: 0, 159 Result.FAIL: 0, 160 Result.ERROR: 0, 161 Result.UNTESTED: 0} 162 for r in self.GetAllRuns(): 163 result = r.GetResult(id, kind) 164 if result: 165 outcomes[result.GetOutcome()] += 1 166 else: 167 outcomes[Result.UNTESTED] += 1 168 return outcomes
169

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.executable-pysrc.html0000664000076400007640000112123611122067160024557 0ustar stefanstefan qm.executable
Package qm :: Module executable
[hide private]
[frames] | no frames]

Source Code for Module qm.executable

   1  ######################################################################## 
   2  # 
   3  # File:   executable.py 
   4  # Author: Mark Mitchell 
   5  # Date:   11/14/2002 
   6  # 
   7  # Contents: 
   8  #   Executable, RedirectedExecutable 
   9  # 
  10  # Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
  11  # 
  12  ######################################################################## 
  13   
  14  ######################################################################## 
  15  # Imports 
  16  ####################################################################### 
  17   
  18  import os 
  19  import qm.common 
  20  import signal 
  21  import string 
  22  import sys 
  23  import time 
  24   
  25  # The classes in this module are implemented differently depending on 
  26  # the operating system in use. 
  27  if sys.platform == "win32": 
  28      import msvcrt 
  29      import pywintypes 
  30      from   threading import * 
  31      import win32api 
  32      import win32con 
  33      import win32event 
  34      import win32file 
  35      import win32pipe 
  36      import win32process 
  37  else: 
  38      import cPickle 
  39      import fcntl 
  40      import select 
  41      import qm.sigmask 
  42       
  43  ######################################################################## 
  44  # Classes 
  45  ####################################################################### 
  46   
47 -class Executable(object):
48 """An 'Executable' is a program that the operating system can run. 49 50 'Exectuable' (and classes derived from it) create child processes. 51 The 'Spawn' function creates child processes that execute 52 asynchronously. The 'Run' function creates child processes that 53 execute synchrounously, i.e,. the 'Run' function does not return 54 until the child process has completed its execution. 55 56 It is safe to reuse a particular 'Executable' instance (by calling 57 'Spawn' or 'Run' more than once), so long as the uses are not 58 interleaved.""" 59
60 - def Spawn(self, arguments=[], environment = None, dir = None, 61 path = None, exception_pipe = None):
62 """Spawn the program. 63 64 'arguments' -- The sequence of arguments that should be passed 65 to the executable. The first argument provided in this 66 sequence will be 'argv[0]'; that is also the value used for 67 the path to the executable. 68 69 'environment' -- If not 'None', a dictionary giving the 70 environment that should be provided to the child. 71 72 'dir' -- If not 'None', the directory in which the child 73 should begin execution. If 'None', the child will execute in 74 the same directory as the parent. 75 76 'path' -- If not 'None', the path to the program to run. If 77 'None', 'arguments[0]' is used. 78 79 'exception_pipe' -- If not 'None', a pipe that the child can 80 use to communicate an exception to the parent. This pipe is 81 only used on UNIX systems. The write end of the pipe will be 82 closed by this function. 83 84 returns -- The PID of the child. 85 86 Before creating the child, the parent will call 87 'self._InitializeParent'. On UNIX systems, the child will 88 call 'self._InitializeChild' after 'fork', but before 'exec'. 89 On non-UNIX systems, 'self._InitializeChild' will never be 90 called. 91 92 After creating the child, 'self._HandleChild' is called in the 93 parent. This hook should be used to handle tasks that must be 94 performed after the child is running. 95 96 If the path to the program is absolute, or contains no 97 separator characters, it is not modified. Otherwise the path 98 to the program is relative, it is transformed into an absolute 99 path using 'dir' as the base, or the current directory if 100 'dir' is not set.""" 101 102 # Remember the directory in which the execution will occur. 103 self.__dir = dir 104 105 # The path to the executable is the first argument, if not 106 # explicitly specified. 107 if not path: 108 path = arguments[0] 109 110 # Normalize the path name. At the conclusion of this 111 # processing, the path is either an absolute path, or contains 112 # no directory seperators. 113 if os.path.isabs(path): 114 # An absolute path. 115 pass 116 elif (os.sep in path or (os.altsep and os.altsep in path)): 117 # A relative path name, like "./program". 118 if dir: 119 path = os.path.normpath(os.path.join(dir, path)) 120 if not os.path.isabs(path): 121 path = os.path.abspath(path) 122 else: 123 path = os.path.abspath(path) 124 else: 125 # A path with no directory separators. The program to 126 # execute will be found by searching the PATH environment 127 # variable. 128 pass 129 130 # Initialize the parent. 131 startupinfo = self._InitializeParent() 132 133 # Initialize self.__child so that if "fork" or "CreateProcess" 134 # throws an exception our caller can tell that there is no 135 # child process to kill. 136 self.__child = None 137 138 if sys.platform == "win32": 139 # Compute the command line. The Windows API uses a single 140 # string as the command line, rather than an array of 141 # arguments. 142 command_line = self.__CreateCommandLine(arguments) 143 144 # If the path is not absolute, then we need to search the 145 # PATH. Since CreateProcess only searches the PATH if its 146 # first argument is None, we clear path here. 147 if not os.path.isabs(path): 148 path = None 149 150 # Windows supports wide-characters in the environment, but 151 # the Win32 extensions to Python require that all of the 152 # entries in the environment be of the same type, 153 # i.e,. that either all of them be of type StringType or 154 # of type UnicodeType. Therefore, if we find any elements 155 # that are Unicode strings, convert all of them to Unicode 156 # strings. 157 if environment is not None: 158 # See if there any Unicode strings in the environment. 159 uses_unicode = 0 160 for (k, v) in environment.iteritems(): 161 if (isinstance(k, unicode) 162 or isinstance(v, unicode)): 163 uses_unicode = 1 164 break 165 # If there are Unicode strings in the environment, 166 # convert all of the key-value pairs to Unicode. 167 if uses_unicode: 168 new_environment = {} 169 for (k, v) in environment.iteritems(): 170 new_environment[unicode(k)] = unicode(v) 171 environment = new_environment 172 173 # Create the child process. 174 self.__child \ 175 = win32process.CreateProcess(path, 176 command_line, 177 None, 178 None, 179 1, 180 0, 181 environment, 182 self.__dir, 183 startupinfo)[0] 184 else: 185 # Fork. 186 self.__child = os.fork() 187 188 if self.__child == 0: 189 try: 190 # Close the read end of the pipe. 191 if exception_pipe: 192 os.close(exception_pipe[0]) 193 # Initialize the child. 194 self._InitializeChild() 195 # Exec the program. 196 if environment: 197 os.execvpe(path, arguments, environment) 198 else: 199 os.execvp(path, arguments) 200 except: 201 if exception_pipe: 202 # Get the exception information. 203 exc_info = sys.exc_info() 204 # Write it to the pipe. The traceback object 205 # cannot be pickled, unfortunately, so we 206 # cannot communicate that information. 207 cPickle.dump(exc_info[:2], 208 os.fdopen(exception_pipe[1], "w"), 209 1) 210 # Exit without running cleanups. 211 os._exit(1) 212 213 # This code should never be reached. 214 assert None 215 216 # Nothing will be written to the exception pipe in the parent. 217 if exception_pipe: 218 os.close(exception_pipe[1]) 219 220 # Let the parent take any actions required after creating the 221 # child. 222 self._HandleChild() 223 224 return self.__child
225 226
227 - def Run(self, arguments=[], environment = None, dir = None, 228 path = None):
229 """Spawn the program and wait for it to finish. 230 231 'arguments' -- The sequence of arguments that should be passed 232 to the executable. The first argument provided in this 233 sequence will be 'argv[0]'. 234 235 'environment' -- If not 'None', a dictionary giving the 236 environment that should be provided to the child. If 'None', 237 the child will inherit the parents environment. 238 239 'dir' -- If not 'None', the directory in which the child 240 should begin execution. If 'None', the child will execute in 241 the same directory as the parent. 242 243 'path' -- If not 'None', the path to the program to run. If 244 'None', 'arguments[0]' is used. 245 246 returns -- The status returned by the program. Under UNIX, 247 this is the value returned by 'waitpid'; under Windows, it is 248 the value returned by 'GetExitCodeProcess'. 249 250 After invoking 'Spawn', this function invokes '_DoParent' to 251 allow the parent process to perform whatever actions are 252 required. After that function returns, the parent waits for 253 the child process to exit.""" 254 255 # If fork succeeds, but the exec fails, we want information 256 # about *why* it failed. The exit code from the subprocess is 257 # not nearly as illuminating as the exception raised by exec. 258 # Therefore, we create a pipe between the parent and child; 259 # the child writes the exception into the pipe to communicate 260 # it to the parent. 261 if sys.platform != "win32": 262 exception_pipe = os.pipe() 263 # Mark the write end as close-on-exec so that the file 264 # descriptor is not passed on to the child. 265 qm.common.close_file_on_exec(exception_pipe[1]) 266 else: 267 exception_pipe = None 268 269 # Start the program. 270 child = self.Spawn(arguments, environment, dir, path, exception_pipe) 271 272 # Give the parent a chance to do whatever it needs to do. 273 self._DoParent() 274 275 # Wait for the child to exit. 276 if sys.platform == "win32": 277 win32event.WaitForSingleObject(child, win32event.INFINITE) 278 # Get its exit code. 279 return win32process.GetExitCodeProcess(child) 280 else: 281 status = os.waitpid(child, 0)[1] 282 # See if an exception was pushed back up the pipe. 283 data = os.fdopen(exception_pipe[0]).read() 284 # If any data was read, then it is data corresponding to 285 # the exception thrown by exec. 286 if data: 287 # Unpickle the data. 288 exc_info = cPickle.loads(data) 289 # And raise it here. 290 raise exc_info[0], exc_info[1] 291 292 return status
293 294
295 - def _InitializeParent(self):
296 """Initialize the parent process. 297 298 Before spawning the child, this method is invoked to give the 299 parent a chance to initialize itself. 300 301 returns -- Under Windows, a 'PySTARTUPINFO' structure 302 explaining how the child should be initialized. On other 303 systems, the return value is ignored.""" 304 305 if sys.platform == "win32": 306 return win32process.STARTUPINFO()
307 308
309 - def Kill(self):
310 """Kill the child process. 311 312 The child process is killed in a way that does not permit an 313 orderly shutdown. In other words, 'SIGKILL' is used under 314 UNIX, not 'SIGTERM'. On Windows, 'TerminateProcess' is used, 315 and the exit code from the child process will be '1'.""" 316 317 if sys.platform == "win32": 318 win32process.TerminateProcess(self._GetChildPID(), 1) 319 else: 320 os.kill(self._GetChildPID(), signal.SIGKILL)
321 322
323 - def _HandleChild(self):
324 """Run in the parent process after the child has been created. 325 326 The child process has been spawned; its PID is avialable via 327 '_GetChildPID'. Take any actions in the parent that are 328 required now that the child exists. 329 330 Derived class versions must call this method.""" 331 332 pass
333 334
335 - def _InitializeChild(self):
336 """Initialize the child process. 337 338 After 'fork' is called this method is invoked to give the 339 child a chance to initialize itself. '_InitializeParent' will 340 already have been called in the parent process. 341 342 This method is not used under Windows.""" 343 344 assert sys.platform != "win32" 345 346 # The way Python's threading support works, every thread except 347 # the main thread always has all signals blocked. This is fine 348 # for the threads themselves, but it causes problems if we 349 # 'fork' from a child thread; the new process starts with all 350 # signals blocked, which is probably not what you want! 351 # Arguably this is a bug in Python, but for the meantime, work 352 # around this by setting the new process's signal mask to match 353 # the signal mask that QMTest was started with. 354 qm.sigmask.restore_mask() 355 356 if self.__dir: 357 os.chdir(self.__dir)
358 359
360 - def _DoParent(self):
361 """Perform actions required in the parent after 'Spawn'.""" 362 363 pass
364 365
366 - def _GetChildPID(self):
367 """Return the process ID for the child process. 368 369 returns -- The process ID for the child process. (On Windows, 370 the value returned is the process handle.) Returns 'None' if 371 the child has not yet been created, or if something went awry 372 when creating it. For example, if 'os.fork' throws an 373 exception, this value will return 'None'.""" 374 375 return self.__child
376 377
378 - def __CreateCommandLine(self, arguments):
379 """Return a string giving the process command line. 380 381 arguments -- A sequence of arguments (including argv[0]) 382 indicating the command to be run. 383 384 returns -- A string that could be provided to the shell in 385 order to run the command.""" 386 387 command = "" 388 need_space = 0 389 for a in arguments: 390 # Add a space between arguments. 391 if need_space: 392 command += " " 393 else: 394 need_space = 1 395 # If the argument contains whitespace characters, enclose 396 # it in quotes. Similarly, an empty argument must be 397 # enclosed in quotes. 398 if not a: 399 command += '""' 400 continue 401 whitespace = 0 402 for c in string.whitespace: 403 if c in a: 404 whitespace = 1 405 break 406 if whitespace: 407 command += '"' + a + '"' 408 else: 409 command += a 410 411 return command
412 413 414
415 -class TimeoutExecutable(Executable):
416 """A 'TimeoutExecutable' runs for a limited time. 417 418 If the timer expires, the child process is killed and 419 self.timedout is set to 1. Otherwise, self.timedout is set to 0. 420 421 In order to implement this functionality under UNIX, the child 422 process is placed into its own process group. An additional 423 monitoring process is created whose sole job is to kill the 424 primary child's process group if the timeout expires. Process 425 groups are used so that if the child process spawns additional 426 processes they are killed too. A separate monitoring process is 427 used so as not to block the parent. 428 429 Under Windows, a monitoring thread is created. When the timer 430 expires, the child process is terminated. However, the child 431 process is not placed into a separate process group, so 432 granchildren kare not terminated. In the future, when Python 433 provides access to 'CreateJobObject' and related functions, jobs 434 will be used to provide functionality similar to UNIX process 435 groups. 436 437 The 'Run' method will automatically start the monitoring process. 438 The 'Spawn' method does not start the monitoring process. User's 439 of 'Spawn' should invoke '_DoParent' in order to start the 440 monitoring process. Derived class '_DoParent' functions should 441 call the version defined in this class.""" 442
443 - def __init__(self, timeout = -1):
444 """Construct a new 'TimeoutExecutable'. 445 446 'timeout' -- The number of seconds that the child is permitted 447 to run. This value may be a floating-point value. However, 448 the value may be rounded to an integral value on some systems. 449 Once the timeout expires, the child and its entire process 450 group is killed. (The processes in the process group are sent 451 the 'SIGKILL' signal.) If the 'timeout' is -2, the child is 452 allowed to run forever, but when it terminates the child's 453 process group is killed. 454 455 If the 'timeout' is -1, this class behaves exactly like 456 'Executable'.""" 457 458 super(TimeoutExecutable, self).__init__() 459 self.__timeout = float(timeout)
460 461
462 - def _InitializeChild(self):
463 464 # Put the child into its own process group. This step is 465 # performed in both the parent and the child; therefore both 466 # processes can safely assume that the creation of the process 467 # group has taken place. 468 if self.__UseSeparateProcessGroupForChild(): 469 os.setpgid(0, 0) 470 471 super(TimeoutExecutable, self)._InitializeChild()
472 473
474 - def _HandleChild(self):
475 476 super(TimeoutExecutable, self)._HandleChild() 477 478 if self.__UseSeparateProcessGroupForChild(): 479 # Put the child into its own process group. This step is 480 # performed in both the parent and the child; therefore both 481 # processes can safely assume that the creation of the process 482 # group has taken place. 483 child_pid = self._GetChildPID() 484 try: 485 os.setpgid(child_pid, child_pid) 486 except: 487 # The call to setpgid may fail if the child has exited, 488 # or has already called 'exec'. In that case, we are 489 # guaranteed that the child has already put itself in the 490 # desired process group. 491 pass 492 493 # Create the monitoring process. 494 # 495 # If the monitoring process is in parent's process group and 496 # kills the child after waitpid has returned in the parent, we 497 # may end up trying to kill a process group other than the one 498 # that we intend to kill. Therefore, we put the monitoring 499 # process in the same process group as the child; that ensures 500 # that the process group will persist until the monitoring 501 # process kills it. 502 self.__monitor_pid = os.fork() 503 if self.__monitor_pid != 0: 504 # Make sure that the monitoring process is placed into the 505 # child's process group before the parent process calls 506 # 'waitpid'. In this way, we are guaranteed that the process 507 # group as the child 508 os.setpgid(self.__monitor_pid, child_pid) 509 else: 510 # Put the monitoring process into the child's process 511 # group. We know the process group still exists at 512 # this point because either (a) we are in the process 513 # group, or (b) the parent has not yet called waitpid. 514 os.setpgid(0, child_pid) 515 516 # Close all open file descriptors. They are not needed 517 # in the monitor process. Furthermore, when the parent 518 # closes the write end of the stdin pipe to the child, 519 # we do not want the pipe to remain open; leaving the 520 # pipe open in the monitor process might cause the child 521 # to block waiting for additional input. 522 try: 523 max_fds = os.sysconf("SC_OPEN_MAX") 524 except: 525 max_fds = 256 526 for fd in xrange(max_fds): 527 try: 528 os.close(fd) 529 except: 530 pass 531 532 try: 533 if self.__timeout >= 0: 534 # Give the child time to run. 535 time.sleep (self.__timeout) 536 # Kill all processes in the child process group. 537 os.kill(0, signal.SIGKILL) 538 else: 539 # This call to select will never terminate. 540 select.select ([], [], []) 541 finally: 542 # Exit. This code is in a finally clause so that 543 # we are guaranteed to get here no matter what. 544 os._exit(0) 545 elif self.__timeout >= 0 and sys.platform == "win32": 546 # Create a monitoring thread. 547 self.__monitor_thread = Thread(target = self.__Monitor) 548 self.__monitor_thread.start()
549 550
551 - def Run(self, arguments=[], environment = None, dir = None, 552 path = None):
553 554 if self.__UseSeparateProcessGroupForChild(): 555 self.__monitor_pid = None 556 elif self.__timeout >= 0 and sys.platform == "win32": 557 self.__monitor_thread = None 558 559 # Run the process. 560 try: 561 status = super(TimeoutExecutable, self).Run(arguments, 562 environment, 563 dir, 564 path) 565 finally: 566 if self.__UseSeparateProcessGroupForChild(): 567 # Clean up the monitoring program; it is no longer needed. 568 child_pid = self._GetChildPID() 569 if child_pid is not None: 570 os.kill(-child_pid, signal.SIGKILL) 571 if self.__monitor_pid is not None: 572 os.waitpid(self.__monitor_pid, 0) 573 elif self.__timeout >= 0 and sys.platform == "win32": 574 # Join the monitoring thread. 575 if self.__monitor_thread is not None: 576 self.__monitor_thread.join() 577 578 return status
579 580
582 """Returns true if the child wil be placed in its own process group. 583 584 returns -- True if the child will be placed in its own process 585 group. In that case, a separate monitoring process will also 586 be created.""" 587 588 if sys.platform == "win32": 589 # In Windows 2000 (or later), we should use "jobs" by 590 # analogy with UNIX process groups. However, that 591 # functionality is not (yet) provided by the Python Win32 592 # extensions. 593 return 0 594 595 return self.__timeout >= 0 or self.__timeout == -2
596 597 598 if sys.platform == "win32": 599
600 - def __Monitor(self):
601 """Kill the child if the timeout expires. 602 603 This function is run in the monitoring thread.""" 604 605 # The timeout may be expressed as a floating-point value 606 # on UNIX, but it must be an integer number of 607 # milliseconds when passed to WaitForSingleObject. 608 timeout = int(self.__timeout * 1000) 609 # Wait for the child process to terminate or for the 610 # timer to expire. 611 result = win32event.WaitForSingleObject(self._GetChildPID(), 612 timeout) 613 # If the timeout occurred, kill the child process. 614 if result == win32con.WAIT_TIMEOUT: 615 self.Kill()
616 617 618
619 -class RedirectedExecutable(TimeoutExecutable):
620 """A 'RedirectedExecutable' redirects the standard I/O streams.""" 621
622 - def _InitializeParent(self):
623 624 super(RedirectedExecutable, self)._InitializeParent() 625 626 # Create a pipe for each of the streams. 627 self._stdin_pipe = self._StdinPipe() 628 self._stdout_pipe = self._StdoutPipe() 629 self._stderr_pipe = self._StderrPipe() 630 631 # There has been no output yet. 632 self.stdout = "" 633 self.stderr = "" 634 635 # Under Windows, create a startupinfo structure that explains 636 # where the streams connected to the child should go. 637 if sys.platform == "win32": 638 # Create a startupinfo structure. 639 startupinfo = win32process.STARTUPINFO() 640 # Indicate that the child process should use the standard 641 # handles in startupinfo. 642 startupinfo.dwFlags = win32con.STARTF_USESTDHANDLES 643 644 # Attach each of the pipes to the appropriate entries in 645 # startupinfo. Also create a non-inheritable duplicate of the 646 # pipe end we will be using, and close the inheritable 647 # version. 648 if self._stdin_pipe: 649 startupinfo.hStdInput = self._stdin_pipe[0] 650 self._stdin_pipe[1] \ 651 = self.__UninheritableHandle(self._stdin_pipe[1]) 652 else: 653 startupinfo.hStdInput = win32file.INVALID_HANDLE_VALUE 654 if self._stdout_pipe: 655 startupinfo.hStdOutput = self._stdout_pipe[1] 656 self._stdout_pipe[0] \ 657 = self.__UninheritableHandle(self._stdout_pipe[0]) 658 else: 659 startupinfo.hStdOutput = win32file.INVALID_HANDLE_VALUE 660 if self._stderr_pipe: 661 startupinfo.hStdError = self._stderr_pipe[1] 662 self._stderr_pipe[0] \ 663 = self.__UninheritableHandle(self._stderr_pipe[0]) 664 elif self._stdout_pipe: 665 # If there's no stderr pipe -- but there is a stdout 666 # pipe -- redirect both stdout and stderr to the same 667 # pipe. 668 startupinfo.hStdError = self._stdout_pipe[1] 669 else: 670 startupinfo.hStdError = win32file.INVALID_HANDLE_VALUE 671 672 return startupinfo
673 674
675 - def _InitializeChild(self):
676 677 # Let the base class do any initialization required. 678 super(RedirectedExecutable, self)._InitializeChild() 679 680 # Redirect the standard I/O streams to the pipes. Python does 681 # not provide STDIN_FILENO, STDOUT_FILENO, and STDERR_FILENO, 682 # so we must use the file descriptor numbers directly. 683 if self._stdin_pipe: 684 os.dup2(self._stdin_pipe[0], 0) 685 else: 686 os.close(0) 687 688 if self._stdout_pipe: 689 os.dup2(self._stdout_pipe[1], 1) 690 else: 691 os.close(1) 692 693 if self._stderr_pipe: 694 os.dup2(self._stderr_pipe[1], 2) 695 elif self._stdout_pipe: 696 # If there's no stderr pipe -- but there is a stdout 697 # pipe -- redirect both stdout and stderr to the same 698 # pipe. 699 os.dup2(self._stdout_pipe[1], 2) 700 else: 701 os.close(2) 702 703 # Close the pipe fds. This should happen automatically when we 704 # exec the new process anyway, but it is polite to close fds as 705 # soon as possible. 706 if self._stdin_pipe: 707 os.close(self._stdin_pipe[0]) 708 os.close(self._stdin_pipe[1]) 709 if self._stdout_pipe: 710 os.close(self._stdout_pipe[0]) 711 os.close(self._stdout_pipe[1]) 712 if self._stderr_pipe: 713 os.close(self._stderr_pipe[0]) 714 os.close(self._stderr_pipe[1])
715 716
717 - def _HandleChild(self):
718 719 # Close the pipe ends that we do not need. 720 if self._stdin_pipe: 721 self._ClosePipeEnd(self._stdin_pipe[0]) 722 if self._stdout_pipe: 723 self._ClosePipeEnd(self._stdout_pipe[1]) 724 if self._stderr_pipe: 725 self._ClosePipeEnd(self._stderr_pipe[1]) 726 727 # The pipes created by 'RedirectedExecutable' must be closed 728 # before the monitor process (created by 'TimeoutExecutable') 729 # is created. Otherwise, if the child process dies, 'select' 730 # in the parent will not return if the monitor process may 731 # still have one of the file descriptors open. 732 super(RedirectedExecutable, self)._HandleChild()
733 734
735 - def _DoParent(self):
736 737 super(RedirectedExecutable, self)._DoParent() 738 739 # Process the various redirected streams until none of the 740 # streams remain open. 741 if sys.platform != "win32": 742 while 1: 743 # Prepare the lists of interesting descriptors. 744 read_fds = [] 745 write_fds = [] 746 if self._stdout_pipe: 747 read_fds.append(self._stdout_pipe[0]) 748 if self._stderr_pipe: 749 read_fds.append(self._stderr_pipe[0]) 750 if self._stdin_pipe: 751 write_fds.append(self._stdin_pipe[1]) 752 753 # If there are no longer any interesting descriptors, we are 754 # done. 755 if not read_fds and not write_fds: 756 return 757 758 # See which descriptors are ready for processing. 759 read_ready, write_ready \ 760 = select.select(read_fds, write_fds, [])[:2] 761 762 # Process them. 763 if self._stdout_pipe and self._stdout_pipe[0] in read_ready: 764 self._ReadStdout() 765 if self._stderr_pipe and self._stderr_pipe[0] in read_ready: 766 self._ReadStderr() 767 if self._stdin_pipe and self._stdin_pipe[1] in write_ready: 768 self._WriteStdin() 769 else: 770 # Under Windows, neither select, nor 771 # WaitForMultipleObjects, works on pipes. The only 772 # approach that is reliable under all versions of Windows 773 # is to use a separate thread for each handle. By 774 # converting the pipe ends from OS handles to file 775 # descriptors at this point, _ReadStdout, _ReadStderr, and 776 # _WriteStdin can use the same implementations under 777 # Windows that they do under UNIX. 778 779 if self._stdin_pipe: 780 h = self._stdin_pipe[1] 781 self._stdin_pipe[1] = msvcrt.open_osfhandle(h, 0) 782 h.Detach() 783 stdin_thread = Thread(target = self.__CallUntilNone, 784 args = (self._WriteStdin, 785 "_stdin_pipe")) 786 else: 787 stdin_thread = None 788 789 if self._stdout_pipe: 790 h = self._stdout_pipe[0] 791 self._stdout_pipe[0] = msvcrt.open_osfhandle(h, 0) 792 h.Detach() 793 stdout_thread = Thread(target = self.__CallUntilNone, 794 args = (self._ReadStdout, 795 "_stdout_pipe")) 796 else: 797 stdout_thread = None 798 799 if self._stderr_pipe: 800 h = self._stderr_pipe[0] 801 self._stderr_pipe[0] = msvcrt.open_osfhandle(h, 0) 802 h.Detach() 803 stderr_thread = Thread(target = self.__CallUntilNone, 804 args = (self._ReadStderr, 805 "_stderr_pipe")) 806 else: 807 stderr_thread = None 808 809 # Start the threads. 810 for t in stdin_thread, stdout_thread, stderr_thread: 811 if t: 812 t.start() 813 # Wait for them to finish. 814 for t in stdin_thread, stdout_thread, stderr_thread: 815 if t: 816 t.join()
817 818
819 - def _ReadStdout(self):
820 """Read from the standard output pipe.""" 821 822 # Read some data. 823 data = os.read(self._stdout_pipe[0], 64 * 1024) 824 825 if not data: 826 # If there is no new data, end-of-file has been reached. 827 os.close(self._stdout_pipe[0]) 828 self._stdout_pipe = None 829 else: 830 # Otherwise, add the data to the output we have already 831 # collected. 832 self.stdout += data
833 834
835 - def _ReadStderr(self):
836 """Read from the standard error pipe.""" 837 838 # Read some data. 839 data = os.read(self._stderr_pipe[0], 64 * 1024) 840 841 if not data: 842 # If there is no new data, end-of-file has been reached. 843 os.close(self._stderr_pipe[0]) 844 self._stderr_pipe = None 845 else: 846 # Otherwise, add the data to the output we have already 847 # collected. 848 self.stderr += data
849 850
851 - def _WriteStdin(self):
852 """Write to the standard input pipe. 853 854 This implementation writes no data and closes the pipe.""" 855 856 # Close the pipe. 857 os.close(self._stdin_pipe[1]) 858 self._stdin_pipe = None
859 860
861 - def _StdinPipe(self):
862 """Return a pipe to which to redirect the standard input. 863 864 returns -- A pipe, or 'None' if the standard input should be 865 closed in the child.""" 866 867 pipe = self._CreatePipe() 868 if sys.platform != "win32": 869 # Make sure that writing to the pipe will never result in 870 # deadlock. 871 fcntl.fcntl(pipe[1], fcntl.F_SETFL, 872 fcntl.fcntl(pipe[1], fcntl.F_GETFL) | os.O_NONBLOCK) 873 return pipe
874 875
876 - def _StdoutPipe(self):
877 """Return a pipe to which to redirect the standard output. 878 879 returns -- A pipe, or 'None' if the standard output should be 880 closed in the child.""" 881 882 return self._CreatePipe()
883 884
885 - def _StderrPipe(self):
886 """Return a pipe to which to redirect the standard input. 887 888 returns -- A pipe, or 'None'. If 'None' is returned, but 889 '_StdoutPipe' returns a pipe, then the standard error and 890 standard input will both be redirected to that pipe. However, 891 if '_StdoutPipe' also returns 'None', then the standard error 892 will be closed in the child.""" 893 894 return self._CreatePipe()
895 896
897 - def _ClosePipeEnd(self, fd):
898 """Close the file descriptor 'fd', which is one end of a pipe. 899 900 'fd' -- Under UNIX, a file descriptor. Under Windows, a 901 handle.""" 902 903 if sys.platform == "win32": 904 fd.Close() 905 else: 906 os.close(fd)
907 908
909 - def _CreatePipe(self):
910 """Return a new pipe. 911 912 returns -- A tuple (under UNIX) or list (under Windows) 913 consisting of the file descriptors (UNIX) or handles (Windows) 914 for the read end and write end of a new pipe. The pipe is 915 inheritable by child processes. On UNIX the fds will not be 916 inherited across 'exec'.""" 917 918 if sys.platform == "win32": 919 # Create a security descriptor so that we can mark the handles 920 # as inheritable. (A call to os.pipe under Windows 921 # returns handles that are not inheritable.) 922 sa = pywintypes.SECURITY_ATTRIBUTES() 923 sa.bInheritHandle = 1 924 # Transform the tuple returned into a list so that the 925 # individual elements can be altered. 926 r, w = win32pipe.CreatePipe(sa, 0) 927 return [r, w] 928 else: 929 pipe = os.pipe() 930 for fd in pipe: 931 qm.common.close_file_on_exec(fd) 932 return pipe
933 934
935 - def __CallUntilNone(self, f, attribute):
936 """Call 'f' until 'self.attribute' is 'None'. 937 938 'f' -- A callable. 939 940 'attribute' -- A string giving the name of an attribute.""" 941 942 while getattr(self, attribute) is not None: 943 f()
944 945
946 - def __UninheritableHandle(self, handle):
947 """Return a duplicate of a file handle that is not inheritable. 948 949 'handle' -- A file handle. 950 951 returns -- A new handle that is a non-inheritable duplicate of 952 the 'handle'. 953 954 This method should only be used under Windows.""" 955 956 assert sys.platform == "win32" 957 958 current_process = win32api.GetCurrentProcess() 959 return win32api.DuplicateHandle(current_process, 960 handle, 961 current_process, 962 0, 963 0, 964 win32con.DUPLICATE_SAME_ACCESS)
965 966 967
968 -class Filter(RedirectedExecutable):
969 """A 'FilterExecutable' feeds an input string to another proces. 970 971 The input string is provided to a child process via a pipe; the 972 standard output and standard error streams from the child process 973 are collected in the 'Filter'.""" 974
975 - def __init__(self, input, timeout = -1):
976 """Create a new 'Filter'. 977 978 'input' -- The string containing the input to provide to the 979 child process. 980 981 'timeout' -- As for 'TimeoutExecutable.__init__'.""" 982 983 super(Filter, self).__init__(timeout) 984 self.__input = input 985 self.__next = 0
986 987
988 - def _WriteStdin(self):
989 990 # If there's nothing more to write, stop. 991 if self.__next == len(self.__input): 992 super(Filter, self)._WriteStdin() 993 else: 994 # Write some data. 995 self.__next += os.write(self._stdin_pipe[1], 996 self.__input[self.__next 997 : self.__next + 64 * 1024])
998 999 1000 ######################################################################## 1001 # Variables 1002 ####################################################################### 1003 1004 __all__ = ["Executable", 1005 "TimeoutExecutable", 1006 "RedirectedExecutable", 1007 "Filter"] 1008

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_String.File-class.html0000664000076400007640000004035311122067146032213 0ustar stefanstefan qm.external.DocumentTemplate.DT_String.File
Package qm :: Package external :: Package DocumentTemplate :: Module DT_String :: Class File
[hide private]
[frames] | no frames]

Class File

source code

FileMixin --+
            |
   String --+
            |
           File

Document templates read from files.

If the object is pickled, the file name, rather than the file contents is pickled. When the object is unpickled, then the file will be re-read to obtain the string. Note that the file will not be read until the document template is used the first time.

Instance Methods [hide private]
 
manage_edit(self, data) source code

Inherited from FileMixin: __init__, read_raw

Inherited from String: SubTemplate, ZDocumentTemplate_afterRender, ZDocumentTemplate_beforeRender, __call__, __getstate__, __str__, cook, default, errQuote, id, initvars, munge, name, parse, parseTag, parse_block, parse_close, parse_error, read, setName, skip_eol, tagre, var, varExtra

Inherited from String (private): _parseTag

Class Variables [hide private]
  manage_edit__roles__ = ()

Inherited from FileMixin: edited_source, read_raw__roles__

Inherited from String: SubTemplate__roles__, ZDocumentTemplate_afterRender__roles__, ZDocumentTemplate_beforeRender__roles__, _parseTag__roles__, commands, commands__roles__, cook__roles__, default__roles__, errQuote__roles__, func_code, func_defaults, func_defaults__roles__, initvars__roles__, isDocTemp, munge__roles__, parseTag__roles__, parse__roles__, parse_block__roles__, parse_close__roles__, parse_error__roles__, read__roles__, setName__roles__, shared_globals, shared_globals__roles__, skip_eol__roles__, tagre__roles__, validate, validate__roles__, varExtra__roles__, var__roles__

Method Details [hide private]

manage_edit(self, data)

source code 
Overrides: String.manage_edit

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform-pysrc.html0000664000076400007640000006170411122067153024266 0ustar stefanstefan qm.platform
Package qm :: Module platform
[hide private]
[frames] | no frames]

Source Code for Module qm.platform

 1  ######################################################################## 
 2  # 
 3  # File:   platform.py 
 4  # Author: Alex Samuel 
 5  # Date:   2001-04-30 
 6  # 
 7  # Contents: 
 8  #   Platform-specific code. 
 9  # 
10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # imports 
18  ######################################################################## 
19   
20  import common 
21  import os 
22  import qm 
23  import string 
24  import sys 
25   
26  ######################################################################## 
27  # classes 
28  ######################################################################## 
29   
30 -class MailError(common.QMException):
31 32 pass
33 34 35 ######################################################################## 36 # initialization 37 ######################################################################## 38 39 if sys.platform == "win32": 40 from platform_win32 import * 41 else: 42 from platform_unix import * 43 44 ######################################################################## 45 # functions 46 ######################################################################## 47
49 """Return the command shell to use when running a single shell command. 50 51 returns -- A sequence of argument list entries to use when invoking 52 the shell. The first element of the list is the shell executable 53 path. The command should be appended to the argument list.""" 54 55 shell = common.rc.Get("command_shell", None, "common") 56 if shell is not None: 57 # Split the configuration value into an argument list. 58 return common.split_argument_list(shell) 59 else: 60 if sys.platform == "win32": 61 shell = default_shell + ["/c"] 62 else: 63 shell = default_shell + ["-c"] 64 return shell
65 66
68 """Return the command shell to use when running a shell script. 69 70 returns -- A sequence of argument list entries to use when running a 71 shell script. The first element of the list is the shell 72 executable. The name of the script should be appended to the 73 argument list.""" 74 75 shell = common.rc.Get("script_shell", None, "common") 76 if shell is not None: 77 # Split the configuration value into an argument list. 78 return common.split_argument_list(shell) 79 else: 80 # On Windows, add the "/c" switch; that is needed even when 81 # invoking a script. 82 if sys.platform == "win32": 83 shell = default_shell + ["/c"] 84 else: 85 # Use the default, but copy it so the caller can change it. 86 shell = default_shell[:] 87 return shell
88 89 90 ######################################################################## 91 # Local Variables: 92 # mode: python 93 # indent-tabs-mode: nil 94 # fill-column: 72 95 # End: 96

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.expectation_database-module.html0000664000076400007640000001122611122067145027707 0ustar stefanstefan qm.test.expectation_database
Package qm :: Package test :: Module expectation_database
[hide private]
[frames] | no frames]

Module expectation_database

source code

Classes [hide private]
  ExpectationDatabase
An 'ExpectationDatabase' stores result expectations.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.platform_unix-pysrc.html0000664000076400007640000017033311122067152025327 0ustar stefanstefan qm.platform_unix
Package qm :: Module platform_unix
[hide private]
[frames] | no frames]

Source Code for Module qm.platform_unix

  1  ######################################################################## 
  2  # 
  3  # File:   platform_unix.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-05-13 
  6  # 
  7  # Contents: 
  8  #   Platform-specific function for UNIX and UNIX-like systems. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import base64 
 21  import common 
 22  import cPickle 
 23  import cStringIO 
 24  import os 
 25  import posix 
 26  import qm 
 27  import quopri 
 28  import select 
 29  import signal 
 30  import string 
 31  import sys 
 32  import traceback 
 33   
 34  ######################################################################## 
 35  # constants 
 36  ######################################################################## 
 37   
 38  if sys.platform[:5] == "linux": 
 39      # GNU/Linux systems generally use 'bash' as the default shell. 
 40      # Invoke it with options to inhibit parsing of user startup files. 
 41      default_shell = ["/bin/bash", "-norc", "-noprofile"] 
 42  else: 
 43      # Other UNIX systems use the Bourne shell. 
 44      default_shell = ["/bin/sh"] 
 45   
 46   
 47  ######################################################################## 
 48  # classes 
 49  ######################################################################## 
 50   
51 -class SignalException(common.QMException):
52 """An exception raised in response to a signal.""" 53
54 - def __init__(self, signal_number):
55 """Create a new signal exception. 56 57 'signal_number' -- The signal number.""" 58 59 # Construct a text argument for the exception. 60 message = "Signal %d" % signal_number 61 # Include the signal name, if available. 62 signal_name = get_signal_name(signal_number) 63 if signal_name is not None: 64 message = message + " (%s)" % signal_name 65 # Initialize the base class. 66 common.QMException.__init__(self, message) 67 # Store the signal number. 68 self.__signal_number = signal_number
69 70
71 - def GetSignalNumber(self):
72 """Return the number of the signal that caused this exception.""" 73 74 return self.__signal_number
75 76 77 78 ######################################################################## 79 # functions 80 ######################################################################## 81
82 -def open_in_browser(url):
83 """Open a browser window and point it at 'url'. 84 85 The browser is run in a separate, independent process.""" 86 87 # Escape single quotes in the URL. 88 url = string.replace(url, "'", "%27") 89 # Which browser to use? 90 browser = common.rc.Get("browser", "mozilla", "common") 91 # Invoke the browser. 92 os.system("%s '%s' &" % (browser, url))
93 94
95 -def get_signal_name(signal_number):
96 """Return the name for signal 'signal_number'. 97 98 returns -- The signal's name, or 'None'.""" 99 100 # A hack: look for an attribute in the 'signal' module whose 101 # name starts with "SIG" and whose value is the signal number. 102 for attribute_name in dir(signal): 103 if len(attribute_name) > 3 \ 104 and attribute_name[:3] == "SIG" \ 105 and getattr(signal, attribute_name) == signal_number: 106 return attribute_name 107 # No match. 108 return None
109 110
111 -def install_signal_handler(signal_number):
112 """Install a handler to translate a signal into an exception. 113 114 The signal handler raises a 'SignalException' exception in 115 response to a signal.""" 116 117 signal.signal(signal_number, _signal_handler)
118 119
120 -def _signal_handler(signal_number, execution_frame):
121 """Generic signal handler that raises an exception.""" 122 123 raise SignalException(signal_number)
124 125
126 -def get_host_name():
127 """Return the name of this computer.""" 128 129 return posix.uname()[1]
130 131 ######################################################################## 132 # initialization 133 ######################################################################## 134
135 -def _initialize():
136 """Perform module initialization.""" 137 138 # Install signal handlers for several common signals. 139 for s in (signal.SIGALRM, 140 signal.SIGHUP, 141 signal.SIGTERM, 142 signal.SIGUSR1, 143 signal.SIGUSR2): 144 install_signal_handler(s)
145 146 _initialize() 147 148 ######################################################################## 149 # Local Variables: 150 # mode: python 151 # indent-tabs-mode: nil 152 # fill-column: 72 153 # End: 154

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.DatabaseError-class.html0000664000076400007640000001634311122067150027642 0ustar stefanstefan qm.test.database.DatabaseError
qm :: test :: database :: DatabaseError :: Class DatabaseError
[hide private]
[frames] | no frames]

Class DatabaseError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  DatabaseError
Known Subclasses:

An exception relating to a 'Database'.

All exceptions raised directly by 'Database', or its derived classes, will be instances of 'DatabaseError', or a class derived from 'DatabaseError'.

If QMTest catches the exception, it will treat the string representation of the exception as an error message to be formatted for the user.

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_test-module.html0000664000076400007640000001126411122067145027652 0ustar stefanstefan qm.test.classes.dejagnu_test
Package qm :: Package test :: Package classes :: Module dejagnu_test
[hide private]
[frames] | no frames]

Module dejagnu_test

source code

Classes [hide private]
  DejaGNUTest
A 'DejaGNUTest' emulates a DejaGNU test.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.HttpRedirect-class.html0000664000076400007640000002214611122067151025557 0ustar stefanstefan qm.web.HttpRedirect
Package qm :: Module web :: Class HttpRedirect
[hide private]
[frames] | no frames]

Class HttpRedirect

source code

              object --+        
                       |        
exceptions.BaseException --+    
                           |    
        exceptions.Exception --+
                               |
                              HttpRedirect

Exception signalling an HTTP redirect response.

A script registered with a 'WebServer' instance can raise this exception instead of returning HTML source text, to indicate that the server should send an HTTP redirect (code 302) response to the client instead of the usual code 202 response.

The exception argument is the URL of the redirect target. The 'request' attribute contains a 'WebRequest' for the redirect target.

Instance Methods [hide private]
 
__init__(self, redirect_target_request)
Construct a redirection exception.
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, redirect_target_request)
(Constructor)

source code 

Construct a redirection exception.

'redirect_target_request' -- The 'WebRequest' to which to redirect the client.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.trace-module.html0000664000076400007640000001072211122067145023660 0ustar stefanstefan qm.trace
Package qm :: Module trace
[hide private]
[frames] | no frames]

Module trace

source code

Classes [hide private]
  Tracer
A 'Tracer' outputs trace messages useful for debugging.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.common.UserError-class.html0000664000076400007640000001555411122067145025631 0ustar stefanstefan qm.common.UserError
Package qm :: Module common :: Class UserError
[hide private]
[frames] | no frames]

Class UserError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
                     QMException --+
                                   |
                                  UserError
Known Subclasses:

Instance Methods [hide private]

Inherited from QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.NoSuchTestError-class.html0000664000076400007640000002263111122067150030172 0ustar stefanstefan qm.test.database.NoSuchTestError
qm :: test :: database :: NoSuchTestError :: Class NoSuchTestError
[hide private]
[frames] | no frames]

Class NoSuchTestError

source code

              object --+                    
                       |                    
exceptions.BaseException --+                
                           |                
        exceptions.Exception --+            
                               |            
              common.QMException --+        
                                   |        
                       DatabaseError --+    
                                       |    
                         NoSuchItemError --+
                                           |
                                          NoSuchTestError

The specified test does not exist.

Instance Methods [hide private]
 
__init__(self, test_id)
Construct a new 'NoSuchTestError'
source code

Inherited from NoSuchItemError: __str__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, test_id)
(Constructor)

source code 

Construct a new 'NoSuchTestError'

'test_id' -- The name of the test that does not exist.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.tet_stream-pysrc.html0000664000076400007640000056066711122067153027237 0ustar stefanstefan qm.test.classes.tet_stream
Package qm :: Package test :: Package classes :: Module tet_stream
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.tet_stream

  1  ######################################################################## 
  2  # 
  3  # File:   tet_stream.py 
  4  # Author: Nathaniel Smith 
  5  # Date:   2004-02-11 
  6  # 
  7  # Contents: 
  8  #   TETStream 
  9  # 
 10  # Copyright (c) 2004 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  from   dejagnu_test import DejaGNUTest 
 21  import qm.fields 
 22  import qm.common 
 23  from   qm.test.file_result_stream import FileResultStream 
 24  from   qm.test.result import Result 
 25  import time 
 26   
 27  ######################################################################## 
 28  # Classes 
 29  ######################################################################## 
 30   
31 -class TETStream(FileResultStream):
32 """A 'TETStream' formats results as a TET journal. 33 34 Provides special handling for 'DejaGNUTest' results. 35 36 TET: http://tetworks.opengroup.org/ 37 TET journal format: see appendix C and D of 38 http://tetworks.opengroup.org/documents/3.7/uguide.pdf 39 40 For the meaning of TET result codes, we use as guidelines the LSB 41 test faq, question Q1.11: 42 * PASS - a test result belonging to this group is considered to 43 be a pass for compliance testing purposes: 44 o Pass - the test has been executed correctly and to 45 completion without any kind of problem 46 o Warning - the functionality is acceptable, but you 47 should be aware that later revisions of the relevant 48 standards or specification may change the requirements 49 in this area. 50 o FIP - additional information is provided which needs to 51 be checked manually. 52 o Unsupported - an optional feature is not available or 53 not supported in the implementation under test. 54 o Not in Use - some tests may not be required in certain 55 test modes or when an interface can be implemented by a 56 macro or function and there are two versions of the test 57 only one is used. 58 o Untested - no test written to check a particular feature 59 or an optional facility needed to perform a test is not 60 available on the system. 61 [There are also "notimp" and "unapproved" cases mentioned in 62 the LSB-FHS README, but they are otherwise undocumented, and 63 don't correspond to any DejaGNU or QMTest outcomes anyway.] 64 * FAIL - a test result belonging to this group is considered to 65 be a fail for compliance testing purposes (unless the failure 66 has been waived by an agreed Problem Report in the 67 Certification Problem Reporting database): 68 o Fail - the interface did not behave as expected. 69 o Uninitiated - the particular test in question did not 70 start to execute. 71 o Unresolved - the test started but did not reach the 72 point where the test was able to report success or 73 failure. 74 o Unreported - a major error occurred during the testset 75 execution. (The TET manual calls this NORESULT.) 76 (From http://www.linuxbase.org/test/lsb-runtime-test-faq.html ) 77 78 DejaGNU test results are described as: 79 * PASS - A test has succeeded. 80 * FAIL - A test has produced the bug it was intended to 81 capture. 82 * WARNING - Declares detection of a minor error in the test case 83 itself. Use WARNING rather than ERROR for cases (such as 84 communication failure to be followed by a retry) where the 85 test case can recover from the error. Note that sufficient 86 warnings will cause a test to go from PASS/FAIL to 87 UNRESOLVED. 88 * ERROR - Declares a severe error in the testing framework 89 itself. An ERROR also causes a test to go from PASS/FAIL to 90 UNRESOLVED. 91 * UNRESOLVED - A test produced indeterminate results. Usually, 92 this means the test executed in an unexpected fashion; this 93 outcome requires that a human being go over results, to 94 determine if the test should have passed or failed. This 95 message is also used for any test that requires human 96 intervention because it is beyond the abilities of the testing 97 framework. Any unresolved test should be resolved to PASS or 98 FAIL before a test run can be considered finished. 99 100 Examples: 101 - a test's execution is interrupted 102 - a test does not produce a clear result (because of 103 WARNING or ERROR messages) 104 - a test depends on a previous test case which failed 105 * UNTESTED - a test case that isn't run for some technical 106 reason. (E.g., a dummy test created as a placeholder for a 107 test that is not yet written.) 108 * UNSUPPORTED - Declares that a test case depends on some 109 facility that does not exist in the testing environment; the 110 test is simply meaningless. 111 (From a combination of DejaGNU manual sections "Core Internal 112 Procedures", "C Unit Testing API", and "A POSIX conforming test 113 framework".) 114 115 """ 116 117 # TET result codes: 118 PASS = (0, "PASS") 119 WARNING = (101, "WARNING") 120 FIP = (102, "FIP") 121 UNSUPPORTED = (4, "UNSUPPORTED") 122 NOTINUSE = (3, "NOTINUSE") 123 UNTESTED = (5, "UNTESTED") 124 125 FAIL = (1, "FAIL") 126 UNINITIATED = (6, "UNINITIATED") 127 UNRESOLVED = (2, "UNRESOLVED") 128 UNREPORTED = (7, "UNREPORTED") 129 130
131 - def __init__(self, arguments = None, **args):
132 133 super(TETStream, self).__init__(arguments, **args) 134 135 self._start_time = "<unknown_start_time>" 136 self._finish_time = "<unknown_finish_time>" 137 self._aborted = False 138 self._username = "<unknown_user>" 139 self._userid = "<unknown_user>" 140 self._version = "<unknown_version>" 141 self._uname = "<unknown_uname>" 142 self._cmdline = "<unknown_command_line>" 143 self._settings = {} 144 145 self._tcc_number = 0 146 self._printed_initial_stuff = False
147 148
149 - def _WriteLine(self, code, data, comment):
150 """Write a line in TET journal format.""" 151 152 self.file.write("%i|%s|%s\n" % (code, data, comment))
153 154
155 - def _IsDejaGNUResult(self, result):
156 """Returns 'True' if 'result' has DejaGNU subtests.""" 157 158 for key in result.keys(): 159 if key.startswith(DejaGNUTest.RESULT_PREFIX): 160 return True 161 return False
162 163
164 - def _TETFormatTime(self, time_string):
165 """Converts an ISO-format date-time to a TET-format date-time. 166 167 returns -- A 2-tuple whose first element is the time as a string, 168 and whose second is the date as a string.""" 169 170 t = time.gmtime(qm.common.parse_time_iso(time_string)) 171 172 return (time.strftime("%H:%M:%S", t), 173 time.strftime("%Y%m%d", t))
174 175
176 - def _ExtractTime(self, result, key):
177 """Extracts the start time from a result.""" 178 179 if result.has_key(key): 180 return self._TETFormatTime(result[key])[0] 181 else: 182 return "00:00:00"
183 184
185 - def WriteAnnotation(self, key, value):
186 187 if key == "qmtest.run.start_time": 188 self._start_time, self._start_date \ 189 = self._TETFormatTime(value) 190 elif key == "qmtest.run.end_time": 191 self._finish_time, self._finish_data \ 192 = self._TETFormatTime(value) 193 elif key == "qmtest.run.aborted" and value == "true": 194 self._aborted = True 195 elif key == "qmtest.run.username": 196 self._username = value 197 elif key == "qmtest.run.userid": 198 self._userid = value 199 elif key == "qmtest.run.version": 200 self._version = "qmtest-" + value 201 elif key == "qmtest.run.uname": 202 self._uname = value 203 elif key == "qmtest.run.command_line": 204 self._cmdline = value 205 else: 206 self._settings[key] = value
207 208
209 - def _WriteInitialStuff(self):
210 """Print TET header information, but only on first call. 211 212 Second and later calls are no-ops.""" 213 214 if self._printed_initial_stuff: 215 return 216 217 # Test case controller start 218 # 0 | version time date | who 219 # who is 220 # "User: <username> (<numeric-id>) TCC Start, Command line: <cmdline>" 221 data = "%s %s %s" % (self._version, 222 self._start_time, 223 self._start_date) 224 who = "User: %s (%s) TCC Start, Command line: %s" \ 225 % (self._username, self._userid, self._cmdline) 226 227 self._WriteLine(0, data, who) 228 # Local system information 229 # 5 | sysname nodename release version machine | text 230 self._WriteLine(5, self._uname, "") 231 # Local system configuration start 232 # 20 | pathname mode | text 233 self._WriteLine(20, "qmtest -1", "Config Start") 234 for item in self._settings.iteritems(): 235 # Configuration variable setting 236 # 30 || variable=value 237 self._WriteLine(30, "", "%s=%s" % item) 238 # Configuration end 239 # 40 || text 240 self._WriteLine(40, "", "Config End") 241 242 self._printed_initial_stuff = True
243 244
245 - def WriteResult(self, result):
246 247 self._WriteInitialStuff() 248 if result.GetKind() == Result.TEST: 249 self._tcc_number += 1 250 if self._IsDejaGNUResult(result): 251 self._WriteDejaGNUResult(result) 252 else: 253 self._WriteTestResult(result) 254 else: 255 # We have a resource result. 256 self._WriteResourceResult(result)
257 258
259 - def _WriteTCStart(self, result):
260 """Write a TET test case start line.""" 261 262 # Test case start 263 # 10 | activity_number testcase_path time | invocable_components 264 started = self._ExtractTime(result, Result.START_TIME) 265 data = "%i %s %s" % (self._tcc_number, 266 "/" + result.GetId(), 267 started) 268 self._WriteLine(10, data, "TC Start")
269 270
271 - def _WriteResultAnnotations(self, result, purpose, 272 num_restrict=None, seq_start=1):
273 """Writes out annotations for a 'result' in TET format. 274 275 Annotations are represented as (sequences of) "test case 276 information" lines. 277 278 'result' -- The 'Result' whose annotations should be written. 279 280 'num_restrict' -- Only write out annotations that end with this 281 number. If the number is '1', also writes out all results that 282 don't end in any number, with "INFO: " prefixed. If 'None', 283 writes out all annotations. 284 285 'seq_start' -- The TET test case information sequence number to 286 start with.""" 287 288 seqnum = seq_start 289 keys = result.keys() 290 keys.sort() 291 for key in keys: 292 value = result[key] 293 prefix = "" 294 if num_restrict is not None: 295 if num_restrict == 1 and key[-1] not in "0123456789": 296 prefix = "INFO: " 297 elif not key.endswith("_%i" % num_restrict): 298 continue 299 300 text = qm.common.html_to_text(value) 301 for line in text.split("\n"): 302 # Test case information 303 # 520 | activity_num tp_num context block sequence | text 304 # 305 # We always set 'tp_num' to zero, because annotations 306 # for us are associated with test cases, not test 307 # purposes. 308 # 'context' is to distinguish text coming from different 309 # subprocesses making up the test purpose; it's 310 # generally the pid. For us, it's always zero. 311 # 'block' is entirely undocumented, and the examples 312 # have it always set to one, so we simply set it to 313 # one as well. 314 # 'sequence' appears to be incremented for each line 315 # within a single test purpose and context. 316 self._WriteLine(520, 317 "%i %i 0 1 %i" % (self._tcc_number, 318 purpose, 319 seqnum), 320 "%s%s: %s" % (prefix, key, line)) 321 seqnum += 1
322 323
324 - def _WriteDejaGNUResult(self, result):
325 """Write out a result that has DejaGNU subtest information.""" 326 327 self._WriteTCStart(result) 328 329 # Get the DejaGNU annotations in sorted order. 330 keys = filter(lambda k: k.startswith(DejaGNUTest.RESULT_PREFIX), 331 result.keys()) 332 keys.sort(lambda k1, k2: cmp(int(k1[len(DejaGNUTest.RESULT_PREFIX):]), 333 int(k2[len(DejaGNUTest.RESULT_PREFIX):]))) 334 335 start_time = self._ExtractTime(result, Result.START_TIME) 336 end_time = self._ExtractTime(result, Result.END_TIME) 337 338 purpose = 1 339 for k in keys: 340 r = result[k] 341 outcome = r[:r.find(":")] 342 # Test purpose start 343 # 200 | activity_number test_purpose_number time | text 344 self._WriteLine(200, 345 "%i %i %s" 346 % (self._tcc_number, purpose, start_time), 347 "TP Start") 348 349 outcome_num, outcome_name \ 350 = { DejaGNUTest.PASS: self.PASS, 351 DejaGNUTest.XPASS: self.PASS, 352 DejaGNUTest.FAIL: self.FAIL, 353 DejaGNUTest.XFAIL: self.FAIL, 354 DejaGNUTest.UNTESTED: self.UNTESTED, 355 DejaGNUTest.UNRESOLVED: self.UNRESOLVED, 356 DejaGNUTest.ERROR: self.UNRESOLVED, 357 DejaGNUTest.WARNING: self.WARNING, 358 # TET's UNSUPPORTED is like a FAIL for tests 359 # that check for optional features; UNTESTED is 360 # the correct correspondent for DejaGNU's 361 # UNSUPPORTED. 362 DejaGNUTest.UNSUPPORTED: self.UNTESTED, 363 }[outcome] 364 # As a special case, check for magic annotation. 365 if result.has_key("test_not_relevant_to_testing_mode"): 366 outcome_num, outcome_name = self.NOTINUSE 367 368 # Write per-purpose annotations: 369 self._WriteResultAnnotations(result, purpose, 370 num_restrict=purpose) 371 372 # Test purpose result 373 # 220 | activity_number tp_number result time | result-name 374 data = "%i %i %i %s" % (self._tcc_number, 375 purpose, 376 outcome_num, 377 end_time) 378 self._WriteLine(220, data, outcome_name) 379 380 purpose += 1 381 382 # Test case end 383 # 80 | activity_number completion_status time | text 384 # "completion status" appears undocumented; it is zero in all of 385 # the documented examples. 386 self._WriteLine(80, 387 "%i 0 %s" % (self._tcc_number, end_time), 388 "TC End")
389 390
391 - def _WriteTestResult(self, result):
392 """Write out a result that does not have DejaGNU annotations.""" 393 394 self._WriteTCStart(result) 395 # Test purpose start 396 # 200 | activity_number test_purpose_number time | text 397 start_time = self._ExtractTime(result, Result.START_TIME) 398 data = "%i 1 %s" % (self._tcc_number, start_time) 399 self._WriteLine(200, data, "TP Start") 400 401 outcome_num, outcome_name = { Result.FAIL: self.FAIL, 402 Result.PASS: self.PASS, 403 Result.UNTESTED: self.UNINITIATED, 404 Result.ERROR: self.UNREPORTED, 405 }[result.GetOutcome()] 406 if result.GetOutcome() == Result.ERROR: 407 # Test case information 408 # 520 | activity_num tp_num context block sequence | text 409 # (see _WriteResultAnnotations for details) 410 self._WriteLine(520, 411 "%i 1 0 1 1" % self._tcc_number, 412 "QMTest ERROR in test " + result.GetId()) 413 self._WriteResultAnnotations(result, 1, seq_start=2) 414 else: 415 self._WriteResultAnnotations(result, 1) 416 417 # Test purpose result 418 # 220 | activity_number tp_number result time | result-name 419 end_time = self._ExtractTime(result, Result.END_TIME) 420 data = "%i 1 %i %s" % (self._tcc_number, outcome_num, end_time) 421 self._WriteLine(220, data, outcome_name) 422 423 # Test case end 424 # 80 | activity_number completion_status time | text 425 # "completion status" appears undocumented; it is zero in all of 426 # the documented examples. 427 self._WriteLine(80, 428 "%i 0 %s" % (self._tcc_number, end_time), 429 "TC End")
430 431
432 - def _WriteResourceResult(self, result):
433 """Write out information on a resource result. 434 435 TET has no concept of resources, so we ignore successful 436 resources, and print out "test case controller messages" for 437 ERRORs and FAILUREs.""" 438 439 if result.GetOutcome() in (Result.FAIL, Result.ERROR): 440 if result.GetKind() == Result.RESOURCE_SETUP: 441 verbing = "setting up" 442 elif result.GetKind() == Result.RESOURCE_CLEANUP: 443 verbing = "cleaning up" 444 else: 445 assert False, "Unexpected result kind" 446 id = result.GetId() 447 outcome = result.GetOutcome() 448 # Test case controller message 449 # 50 || text describing problem 450 self._WriteLine(50, "", "Problem with %s resource %s: %s" 451 % (verbing, id, outcome)) 452 453 for key, value in result.items(): 454 for line in value.split("\n"): 455 self._WriteLine(50, "", "%s: %s" % (key, line))
456 457
458 - def Summarize(self):
459 460 self._WriteInitialStuff() 461 462 if self._aborted: 463 # User abort 464 # 90 | time | text 465 self._WriteLine(90, self._finish_time, "Aborted.") 466 467 # Test case controller end 468 # 900 | time | text 469 self._WriteLine(900, self._finish_time, "Done.")
470

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.host.Host.Executable-class.html0000664000076400007640000002407011122067146026355 0ustar stefanstefan qm.host.Host.Executable
Package qm :: Module host :: Class Host :: Class Executable
[hide private]
[frames] | no frames]

Class Executable

source code

              object --+            
                       |            
   executable.Executable --+        
                           |        
executable.TimeoutExecutable --+    
                               |    
 executable.RedirectedExecutable --+
                                   |
                                  Host.Executable

An 'Executable' is a simple redirected executable.

The standard error and standard output streams are combined
into a single stream.

The standard input is not closed before
invoking the program because SSH hangs if its standard input
is closed before it is invoked.  For example, running:

   ssh machine echo hi <&-

will hang with some versions of SSH.

Instance Methods [hide private]
 
_StderrPipe(self)
Return a pipe to which to redirect the standard input.
source code

Inherited from executable.RedirectedExecutable (private): _ClosePipeEnd, _CreatePipe, _DoParent, _HandleChild, _InitializeChild, _InitializeParent, _ReadStderr, _ReadStdout, _StdinPipe, _StdoutPipe, _WriteStdin

Inherited from executable.TimeoutExecutable: Run, __init__

Inherited from executable.Executable: Kill, Spawn

Inherited from executable.Executable (private): _GetChildPID

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

_StderrPipe(self)

source code 

Return a pipe to which to redirect the standard input.

returns -- A pipe, or 'None'. If 'None' is returned, but '_StdoutPipe' returns a pipe, then the standard error and standard input will both be redirected to that pipe. However, if '_StdoutPipe' also returns 'None', then the standard error will be closed in the child.

Overrides: executable.RedirectedExecutable._StderrPipe
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.queue-module.html0000664000076400007640000000676011122067145023715 0ustar stefanstefan qm.queue
Package qm :: Module queue
[hide private]
[frames] | no frames]

Module queue

source code

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_result_stream-pysrc.html0000664000076400007640000030737211122067152030630 0ustar stefanstefan qm.test.classes.xml_result_stream
Package qm :: Package test :: Package classes :: Module xml_result_stream
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.xml_result_stream

  1  ######################################################################## 
  2  # 
  3  # File:   xml_result_stream.py 
  4  # Author: Mark Mitchell 
  5  # Date:   10/10/2001 
  6  # 
  7  # Contents: 
  8  #   XMLResultStream, XMLResultReader 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ######################################################################## 
 17   
 18  import qm.xmlutil 
 19  from   qm.test.file_result_reader import FileResultReader 
 20  from   qm.test.result import Result 
 21  from   qm.test.file_result_stream import FileResultStream 
 22   
 23  ######################################################################## 
 24  # classes 
 25  ######################################################################## 
 26   
27 -class XMLResultStream(FileResultStream):
28 """An 'XMLResultStream' writes out results as XML. 29 30 An 'XMLResultStream' writes out results as XML. This stream is 31 used to write out QMTest results files. The DTD is designed in 32 such a way that if QMTest is terminated in the middle of a test 33 run, the file will still be nearly valid, as long as the 34 interruption did not occur in the midst of writing out an 35 individual result. The closing tag for the results file will 36 be missing.""" 37
38 - def __init__(self, arguments = None, **args):
39 40 # Initialize the base class. 41 super(XMLResultStream, self).__init__(arguments, **args) 42 43 # Create an XML document, since the DOM API requires you 44 # to have a document when you create a node. 45 self.__document = qm.xmlutil.create_dom_document( 46 public_id="QMTest/Result", 47 document_element_tag="results") 48 # Write out the prologue. 49 self.file.write("<?xml version='1.0' encoding='ISO-8859-1'?>\n") 50 self.file.write('<!DOCTYPE results PUBLIC "%s" "%s">\n' 51 % (qm.xmlutil.make_public_id("QMTest/Result"), 52 qm.xmlutil.make_system_id("qmtest/result.dtd"))) 53 # Begin the list of results. 54 self.file.write("<results>\n")
55 56
57 - def WriteAnnotation(self, key, value):
58 59 element = self.__document.createElement("annotation") 60 element.setAttribute("key", key) 61 text = self.__document.createTextNode(value) 62 element.appendChild(text) 63 element.writexml(self.file, addindent = " ", newl = "\n")
64 65
66 - def WriteResult(self, result):
67 68 element = result.MakeDomNode(self.__document) 69 element.writexml(self.file, indent = " ", addindent = " ", 70 newl = "\n")
71 72
73 - def Summarize(self):
74 75 # Finish the list of results. 76 self.file.write("\n</results>\n") 77 78 FileResultStream.Summarize(self)
79 80 81
82 -class XMLResultReader(FileResultReader):
83 """Reads in 'Result's from an XML-formatted results file. 84 85 To write such a file, see 'XMLResultStream'.""" 86
87 - def __init__(self, arguments = None, **args):
88 89 super(XMLResultReader, self).__init__(arguments, **args) 90 91 # Make sure that this file really is an XML result stream. 92 tag = self.file.read(5) 93 if tag != "<?xml": 94 raise FileResultReader.InvalidFile, \ 95 "file is not an XML result stream" 96 self.file.seek(0) 97 98 document = qm.xmlutil.load_xml(self.file) 99 node = document.documentElement 100 results = node.getElementsByTagName("result") 101 self.__node_iterator = iter(results) 102 103 # Read out annotations 104 self._annotations = {} 105 annotation_nodes = node.getElementsByTagName("annotation") 106 for node in annotation_nodes: 107 key = node.getAttribute("key") 108 value = qm.xmlutil.get_dom_text(node).strip() 109 self._annotations[key] = value
110 111
112 - def GetAnnotations(self):
113 114 return self._annotations
115 116
117 - def GetResult(self):
118 119 try: 120 return self._GetResultFromDomNode(self.__node_iterator.next()) 121 except StopIteration: 122 return None
123 124
125 - def _GetResultFromDomNode(self, node):
126 """Extract a result from a DOM node. 127 128 'node' -- A DOM node corresponding to a "result" element. 129 130 returns -- A 'Result' object.""" 131 132 assert node.tagName == "result" 133 # Extract the outcome. 134 outcome = node.getAttribute("outcome") 135 # If the outcome doesn't exist as an attribute, fall back 136 # to the outcome child node. 137 if not outcome: 138 outcome = qm.xmlutil.get_child_text(node, "outcome").strip() 139 # Extract the test ID. 140 test_id = node.getAttribute("id") 141 kind = node.getAttribute("kind") 142 # Build a Result. 143 result = Result(kind, test_id, outcome) 144 # Extract annotations. 145 for n in node.childNodes: 146 if n.nodeType != node.ELEMENT_NODE: 147 continue 148 if n.tagName == "annotation": 149 quoted = 1 150 elif n.tagName == "property": 151 # Versions of QMTest before 2.1 used the "property" tag, 152 # and did not quote the contained text. 153 quoted = 0 154 else: 155 continue 156 # Get the name of the annotation. 157 name = n.getAttribute("name") 158 # Get the value of the annotation. 159 value = qm.xmlutil.get_dom_text(n) 160 if quoted: 161 # Remove whitespace and then remove the enclosing quotes. 162 value = value.strip()[1:-1] 163 # Remember the annotation. 164 result[name] = value 165 166 return result
167 168 169 170 ######################################################################## 171 # Local Variables: 172 # mode: python 173 # indent-tabs-mode: nil 174 # fill-column: 72 175 # End: 176

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.local_host-module.html0000664000076400007640000001126411122067145027325 0ustar stefanstefan qm.test.classes.local_host
Package qm :: Package test :: Package classes :: Module local_host
[hide private]
[frames] | no frames]

Module local_host

source code

Classes [hide private]
  LocalHost
A 'LocalHost' is the machine on which Python is running.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Var-pysrc.html0000664000076400007640000046457011122067161030662 0ustar stefanstefan qm.external.DocumentTemplate.DT_Var
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Var
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_Var

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13  __doc__='''Variable insertion parameters 
 14   
 15      When inserting variables, parameters may be specified to 
 16      control how the data will be formatted.  In HTML source, the 
 17      'fmt' parameter is used to specify a C-style or custom format 
 18      to be used when inserting an object.  In EPFS source, the 'fmt' 
 19      parameter is only used for custom formats, a C-style format is 
 20      specified after the closing parenthesis. 
 21   
 22      Custom formats 
 23   
 24         A custom format is used when outputing user-defined 
 25         objects.  The value of a custom format is a method name to 
 26         be invoked on the object being inserted.  The method should 
 27         return an object that, when converted to a string, yields 
 28         the desired text.  For example, the DTML code:: 
 29   
 30            <dtml-var date fmt=DayOfWeek> 
 31   
 32         Inserts the result of calling the method 'DayOfWeek' of the 
 33         object bound to the variable 'date', with no arguments. 
 34   
 35         In addition to object methods, serveral additional custom 
 36         formats are available: 
 37   
 38             'whole-dollars' -- Show a numeric value with a dollar symbol. 
 39   
 40             'dollars-and-cents' -- Show a numeric value with a dollar 
 41               symbol and two decimal places. 
 42   
 43             'collection-length' -- Get the length of a collection of objects. 
 44   
 45         Note that when using the EPFS source format, both a 
 46         C-style and a custom format may be provided.  In this case, 
 47         the C-Style format is applied to the result of calling 
 48         the custom formatting method. 
 49   
 50      Null values and missing variables 
 51   
 52         In some applications, and especially in database applications, 
 53         data variables may alternate between "good" and "null" or 
 54         "missing" values.  A format that is used for good values may be 
 55         inappropriate for null values.  For this reason, the 'null' 
 56         parameter can be used to specify text to be used for null 
 57         values.  Null values are defined as values that: 
 58   
 59           - Cannot be formatted with the specified format, and 
 60   
 61           - Are either the special Python value 'None' or 
 62             are false and yield an empty string when converted to 
 63             a string. 
 64   
 65         For example, when showing a monitary value retrieved from a 
 66         database that is either a number or a missing value, the 
 67         following variable insertion might be used:: 
 68   
 69             <dtml-var cost fmt="$%.2d" null=\'n/a\'> 
 70   
 71         Missing values are providing for variables which are not 
 72         present in the name space, rather than raising an NameError, 
 73         you could do this: 
 74   
 75             <dtml-var cost missing=0> 
 76   
 77         and in this case, if cost was missing, it would be set to 0. 
 78         In the case where you want to deal with both at the same time, 
 79         you can use 'default': 
 80   
 81             <dtml-var description default=''> 
 82   
 83         In this case, it would use '' if the value was null or if the 
 84         variable was missing. 
 85   
 86      String manipulation 
 87   
 88         A number of special attributes are provided to transform the 
 89         value after formatting has been applied.  These parameters 
 90         are supplied without arguments. 
 91   
 92         'lower' --  cause all upper-case letters to be converted to lower case. 
 93   
 94         'upper' --  cause all upper-case letters to be converted to lower case. 
 95   
 96         'capitalize' -- cause the first character of the inserted value 
 97         to be converted to upper case. 
 98   
 99         'spacify' -- cause underscores in the inserted value to be 
100         converted to spaces. 
101   
102         'thousands_commas' -- cause commas to be inserted every three 
103         digits to the left of a decimal point in values containing 
104         numbers.  For example, the value, "12000 widgets" becomes 
105         "12,000 widgets". 
106   
107         'html_quote' -- convert characters that have special meaning 
108         in HTML to HTML character entities. 
109   
110         'url_quote' -- convert characters that have special meaning 
111         in URLS to HTML character entities using decimal values. 
112   
113         'url_quote_plus' -- like url_quote but also replace blank 
114         space characters with '+'. This is needed for building 
115         query strings in some cases. 
116   
117         'sql_quote' -- Convert single quotes to pairs of single 
118         quotes. This is needed to safely include values in 
119         Standard Query Language (SQL) strings. 
120   
121         'newline_to_br' -- Convert newlines and carriage-return and 
122         newline combinations to break tags. 
123   
124         'url' -- Get the absolute URL of the object by calling it\'s 
125         'absolute_url' method, if it has one. 
126   
127      Truncation 
128   
129         The attributes 'size' and 'etc'  can be used to truncate long 
130         strings.  If the 'size' attribute is specified, the string to 
131         be inserted is truncated at the given length.  If a space 
132         occurs in the second half of the truncated string, then the 
133         string is further truncated to the right-most space.  After 
134         truncation, the value given for the 'etc' attribute is added to 
135         the string.  If the 'etc' attribute is not provided, then '...' 
136         is used.  For example, if the value of spam is 
137         '"blah blah blah blah"', then the tag        
138         '<!--#var spam size=10-->' inserts '"blah blah ..."'. 
139   
140   
141  Evaluating expressions without rendering results 
142   
143     A 'call' tag is provided for evaluating named objects or expressions 
144     without rendering the result. 
145   
146   
147  ''' # ' 
148  __rcs_id__='$Id: DT_Var.py 1069 2008-11-13 21:55:43Z stefan $' 
149  __version__='$Revision: 1069 $'[11:-2] 
150   
151  from DT_Util import parse_params, name_param, html_quote, str 
152  import string, re, sys 
153  from urllib import quote, quote_plus 
154   
155 -class Var:
156 name='var' 157 expr=None 158
159 - def __init__(self, args, fmt='s'):
160 if args[:4]=='var ': args=args[4:] 161 args = parse_params(args, name='', lower=1, upper=1, expr='', 162 capitalize=1, spacify=1, null='', fmt='s', 163 size=0, etc='...', thousands_commas=1, 164 html_quote=1, url_quote=1, sql_quote=1, 165 url_quote_plus=1, missing='', 166 newline_to_br=1, url=1) 167 self.args=args 168 169 self.modifiers=tuple( 170 map(lambda t: t[1], 171 filter(lambda m, args=args, used=args.has_key: 172 used(m[0]) and args[m[0]], 173 modifiers))) 174 175 name, expr = name_param(args,'var',1) 176 177 self.__name__, self.expr = name, expr 178 self.fmt = fmt 179 180 if len(args)==1 and fmt=='s': 181 if expr is None: expr=name 182 else: expr=expr.eval 183 self.simple_form=(expr,)
184
185 - def render(self, md):
186 args=self.args 187 have_arg=args.has_key 188 name=self.__name__ 189 190 val=self.expr 191 192 if val is None: 193 if md.has_key(name): 194 if have_arg('url'): 195 val=md.getitem(name,0) 196 val=val.absolute_url() 197 else: 198 val = md[name] 199 else: 200 if have_arg('missing'): 201 return args['missing'] 202 else: 203 raise KeyError, name 204 else: 205 val=val.eval(md) 206 if have_arg('url'): val=val.absolute_url() 207 208 __traceback_info__=name, val, args 209 210 if have_arg('null') and not val and val != 0: 211 # check for null (false but not zero, including None, [], '') 212 return args['null'] 213 214 215 # handle special formats defined using fmt= first 216 if have_arg('fmt'): 217 fmt=args['fmt'] 218 if have_arg('null') and not val and val != 0: 219 try: 220 if hasattr(val, fmt): 221 val = getattr(val,fmt)() 222 elif special_formats.has_key(fmt): 223 val = special_formats[fmt](val, name, md) 224 elif fmt=='': val='' 225 else: val = fmt % val 226 except: 227 t, v= sys.exc_type, sys.exc_value 228 if hasattr(sys, 'exc_info'): t, v = sys.exc_info()[:2] 229 if val is None or not str(val): return args['null'] 230 raise t, v 231 232 else: 233 # We duplicate the code here to avoid exception handler 234 # which tends to screw up stack or leak 235 if hasattr(val, fmt): 236 val = getattr(val,fmt)() 237 elif special_formats.has_key(fmt): 238 val = special_formats[fmt](val, name, md) 239 elif fmt=='': val='' 240 else: val = fmt % val 241 242 # finally, pump it through the actual string format... 243 fmt=self.fmt 244 if fmt=='s': val=str(val) 245 else: val = ('%'+self.fmt) % (val,) 246 247 # next, look for upper, lower, etc 248 for f in self.modifiers: val=f(val) 249 250 if have_arg('size'): 251 size=args['size'] 252 try: size=int(size) 253 except: raise 'Document Error',( 254 '''a <code>size</code> attribute was used in a <code>var</code> 255 tag with a non-integer value.''') 256 if len(val) > size: 257 val=val[:size] 258 l=val.rfind(' ') 259 if l > size/2: 260 val=val[:l+1] 261 if have_arg('etc'): l=args['etc'] 262 else: l='...' 263 val=val+l 264 265 return val
266 267 __call__=render
268
269 -class Call:
270 name='call' 271 expr=None 272
273 - def __init__(self, args):
274 args = parse_params(args, name='', expr='') 275 name, expr = name_param(args,'call',1) 276 if expr is None: expr=name 277 else: expr=expr.eval 278 self.simple_form=(expr, None)
279 280
281 -def url_quote(v, name='(Unknown name)', md={}):
282 return quote(str(v))
283
284 -def url_quote_plus(v, name='(Unknown name)', md={}):
285 return quote_plus(str(v))
286
287 -def url_unquote(v, name='(Unknown name)', md={}):
288 return unquote(str(v))
289
290 -def url_unquote_plus(v, name='(Unknown name)', md={}):
291 return unquote_plus(str(v))
292
293 -def newline_to_br(v, name='(Unknown name)', md={}):
294 v=str(v) 295 if v.find('\r') >= 0: v=''.join(v.split('\r')) 296 if v.find('\n') >= 0: v='<br />\n'.join(v.split('\n')) 297 return v
298
299 -def whole_dollars(v, name='(Unknown name)', md={}):
300 try: return "$%d" % v 301 except: return ''
302
303 -def dollars_and_cents(v, name='(Unknown name)', md={}):
304 try: return "$%.2f" % v 305 except: return ''
306
307 -def thousands_commas(v, name='(Unknown name)', md={}, 308 thou=re.compile( 309 r"([0-9])([0-9][0-9][0-9]([,.]|$))").search):
310 v=str(v) 311 vl=v.split('.') 312 if not vl: return v 313 v=vl[0] 314 del vl[0] 315 if vl: s='.'+'.'.join(vl) 316 else: s='' 317 mo=thou(v) 318 while mo is not None: 319 l = mo.start(0) 320 v=v[:l+1]+','+v[l+1:] 321 mo=thou(v) 322 return v+s
323
324 -def whole_dollars_with_commas(v, name='(Unknown name)', md={}):
325 try: v= "$%d" % v 326 except: v='' 327 return thousands_commas(v)
328
329 -def dollars_and_cents_with_commas(v, name='(Unknown name)', md={}):
330 try: v= "$%.2f" % v 331 except: v= '' 332 return thousands_commas(v)
333
334 -def len_format(v, name='(Unknown name)', md={}):
335 return str(len(v))
336
337 -def len_comma(v, name='(Unknown name)', md={}):
338 return thousands_commas(str(len(v)))
339 340 StructuredText=None
341 -def structured_text(v, name='(Unknown name)', md={}):
342 global StructuredText 343 if StructuredText is None: import StructuredText 344 return str(StructuredText.html_with_references(str(v), 3))
345
346 -def sql_quote(v, name='(Unknown name)', md={}):
347 """Quote single quotes in a string by doubling them. 348 349 This is needed to securely insert values into sql 350 string literals in templates that generate sql. 351 """ 352 if v.find("'") >= 0: return v.replace("'", "''") 353 return v
354 355 special_formats={ 356 'whole-dollars': whole_dollars, 357 'dollars-and-cents': dollars_and_cents, 358 'collection-length': len_format, 359 'structured-text': structured_text, 360 361 # The rest are deprecated: 362 'sql-quote': sql_quote, 363 'html-quote': html_quote, 364 'url-quote': url_quote, 365 'url-quote-plus': url_quote_plus, 366 'url-unquote': url_unquote, 367 'url-unquote-plus': url_unquote_plus, 368 'multi-line': newline_to_br, 369 'comma-numeric': thousands_commas, 370 'dollars-with-commas': whole_dollars_with_commas, 371 'dollars-and-cents-with-commas': dollars_and_cents_with_commas, 372 } 373
374 -def spacify(val):
375 if val.find('_') >= 0: val=val.replace('_', ' ') 376 return val
377 378 modifiers=(html_quote, url_quote, url_quote_plus, url_unquote, 379 url_unquote_plus, newline_to_br, 380 string.lower, string.upper, string.capitalize, spacify, 381 thousands_commas, sql_quote, url_unquote, url_unquote_plus) 382 modifiers=map(lambda f: (f.__name__, f), modifiers) 383
384 -class Comment:
385 '''Comments 386 387 The 'comment' tag can be used to simply include comments 388 in DTML source. 389 390 For example:: 391 392 <!--#comment--> 393 394 This text is not rendered. 395 396 <!--#/comment--> 397 ''' 398 name='comment' 399 blockContinuations=() 400
401 - def __init__(self, args, fmt=''): pass
402
403 - def render(self, md):
404 return ''
405 406 __call__=render
407

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.context-module.html0000664000076400007640000001230311122067145025221 0ustar stefanstefan qm.test.context
Package qm :: Package test :: Module context
[hide private]
[frames] | no frames]

Module context

source code

Classes [hide private]
  ContextException
A 'ContextException' indicates an invalid context variable.
  ContextWrapper
Do-nothing class to preserve pickle compatability.
  Context
Test-time and local configuration for tests.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes-module.html0000664000076400007640000000170711122067144025762 0ustar stefanstefan classes

Module classes



[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/int-class.html0000664000076400007640000011122111122067145022554 0ustar stefanstefan int
int :: Class int
[hide private]
[frames] | no frames]

Class int

object --+
         |
        int
Known Subclasses:
  • bool

int(x[, base]) -> integer

Convert a string or number to an integer, if possible. A floating point argument will be truncated towards zero (this does not include a string representation of a floating point number!) When converting a string, use the optional base. It is an error to supply a base when converting a non-string. If the argument is outside the integer range a long object will be returned instead.

Instance Methods [hide private]
 
__abs__(x)
abs(x)
 
__add__(x, y)
x+y
 
__and__(x, y)
x&y
 
__cmp__(x, y)
cmp(x,y)
 
__coerce__(x, y)
coerce(x, y)
 
__div__(x, y)
x/y
 
__divmod__(x, y)
divmod(x, y)
 
__float__(x)
float(x)
 
__floordiv__(x, y)
x//y
 
__getattribute__(...)
x.__getattribute__('name') <==> x.name
 
__getnewargs__(...)
 
__hash__(x)
hash(x)
 
__hex__(x)
hex(x)
 
__index__(...)
x[y:z] <==> x[y.__index__():z.__index__()]
 
__int__(x)
int(x)
 
__invert__(x)
~x
 
__long__(x)
long(x)
 
__lshift__(x, y)
x<<y
 
__mod__(x, y)
x%y
 
__mul__(x, y)
x*y
 
__neg__(x)
-x
a new object with type S, a subtype of T
__new__(T, S, ...)
 
__nonzero__(x)
x != 0
 
__oct__(x)
oct(x)
 
__or__(x, y)
x|y
 
__pos__(x)
+x
 
__pow__(x, y, z=...)
pow(x, y[, z])
 
__radd__(x, y)
y+x
 
__rand__(x, y)
y&x
 
__rdiv__(x, y)
y/x
 
__rdivmod__(x, y)
divmod(y, x)
 
__repr__(x)
repr(x)
 
__rfloordiv__(x, y)
y//x
 
__rlshift__(x, y)
y<<x
 
__rmod__(x, y)
y%x
 
__rmul__(x, y)
y*x
 
__ror__(x, y)
y|x
 
__rpow__(y, x, z=...)
pow(x, y[, z])
 
__rrshift__(x, y)
y>>x
 
__rshift__(x, y)
x>>y
 
__rsub__(x, y)
y-x
 
__rtruediv__(x, y)
y/x
 
__rxor__(x, y)
y^x
 
__str__(x)
str(x)
 
__sub__(x, y)
x-y
 
__truediv__(x, y)
x/y
 
__xor__(x, y)
x^y

Inherited from object: __delattr__, __init__, __reduce__, __reduce_ex__, __setattr__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__getattribute__(...)

 

x.__getattribute__('name') <==> x.name

Overrides: object.__getattribute__

__hash__(x)
(Hashing function)

 

hash(x)

Overrides: object.__hash__

__new__(T, S, ...)

 
Returns: a new object with type S, a subtype of T
Overrides: object.__new__

__repr__(x)
(Representation operator)

 

repr(x)

Overrides: object.__repr__

__str__(x)
(Informal representation operator)

 

str(x)

Overrides: object.__str__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.dist.command.install_extensions-module.html0000664000076400007640000000247711122067144031660 0ustar stefanstefan install_extensions

Module install_extensions


Classes

install_extensions

Functions


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler.CompilerExecutable-class.html0000664000076400007640000003252611122067147032411 0ustar stefanstefan qm.test.classes.compiler.CompilerExecutable
Package qm :: Package test :: Package classes :: Module compiler :: Class CompilerExecutable
[hide private]
[frames] | no frames]

Class CompilerExecutable

source code

              object --+            
                       |            
   executable.Executable --+        
                           |        
executable.TimeoutExecutable --+    
                               |    
 executable.RedirectedExecutable --+
                                   |
                                  CompilerExecutable

A 'CompilerExecutable' is a 'Compiler' that is being run.

Instance Methods [hide private]
 
_InitializeChild(self)
Initialize the child process.
source code
 
_StdinPipe(self)
Return a pipe to which to redirect the standard input.
source code
 
_StderrPipe(self)
Return a pipe to which to redirect the standard input.
source code

Inherited from executable.RedirectedExecutable (private): _ClosePipeEnd, _CreatePipe, _DoParent, _HandleChild, _InitializeParent, _ReadStderr, _ReadStdout, _StdoutPipe, _WriteStdin

Inherited from executable.TimeoutExecutable: Run, __init__

Inherited from executable.Executable: Kill, Spawn

Inherited from executable.Executable (private): _GetChildPID

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

_InitializeChild(self)

source code 

Initialize the child process.

After 'fork' is called this method is invoked to give the child a chance to initialize itself. '_InitializeParent' will already have been called in the parent process.

Overrides: executable.Executable._InitializeChild

_StdinPipe(self)

source code 

Return a pipe to which to redirect the standard input.

returns -- A pipe, or 'None' if the standard input should be closed in the child.

Overrides: executable.RedirectedExecutable._StdinPipe

_StderrPipe(self)

source code 

Return a pipe to which to redirect the standard input.

returns -- A pipe, or 'None'. If 'None' is returned, but '_StdoutPipe' returns a pipe, then the standard error and standard output will both be redirected to that pipe. However, if '_StdoutPipe' also returns 'None', then the standard error will be closed in the child.

Overrides: executable.RedirectedExecutable._StderrPipe

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.structured_text-module.html0000664000076400007640000006532111122067145026037 0ustar stefanstefan qm.structured_text
Package qm :: Module structured_text
[hide private]
[frames] | no frames]

Module structured_text

source code

Functions for parsing, processing, and formatting Python structured text.

See "Structured Text Formatting Rules":http://www.python.org/sigs/doc-sig/stext.html for more information.

Classes [hide private]
  Formatter
Interface for output formatters for the 'StructuredTextProcessor'.
  TextFormatter
Formatter for generating plain text from structured text.
  HtmlFormatter
Formatter for generating HTML from structured text.
  StructuredTextProcessor
Parser and formatter for Python structured text.
Functions [hide private]
 
escape_html_entities(text)
Return 'text' with special characters converted to HTML entities.
source code
 
__format(text, formatter)
Process structured text 'text' with 'formatter'.
source code
 
to_html(structured_text)
Return 'structured_text' formatted as HTML.
source code
 
to_text(structured_text, width=78, indent=0)
Return 'structured_text' formatted as plain text.
source code
 
get_first(structured_text)
Return the first line of 'structured_text'.
source code
 
get_rest(structured_text)
Return the contents of 'structured_text' minus the first line.
source code
 
get_paragraphs(structured_text)
Split 'structured_text' into paragraphs.
source code
 
get_first_paragraph(structured_text)
Return the first paragraph of 'structured_text'.
source code
 
__entity_char_replacement(match, replacement_map={'"': '&quot;', '&': '&amp;', '<': '&lt;', '>': '&gt;', '\xa0'...) source code
Variables [hide private]
  html_help_text = '\n<h4>Structured Text</h4>\n\n<p>Structured ...
  __entity_char_regex = re.compile(r'[\xe5>\xa5\xf2\xc8\xd1\xdd\...
  __paragraph_regexp = re.compile(r'(?:\n *)+\n')
  _verbatim_regexp = re.compile(r'(?s)(\'\'\'.*\'\'\')(?:(?:\n *...
  character = '\xf3'
  entity = 'oacute'
Function Details [hide private]

to_text(structured_text, width=78, indent=0)

source code 

Return 'structured_text' formatted as plain text.

'width' -- The width of the text (including the indentation).

'indent' -- The width of the block indentation of the formatted output.

get_first(structured_text)

source code 

Return the first line of 'structured_text'.

By convention, the first line of a structured text description is a short summary.

get_paragraphs(structured_text)

source code 

Split 'structured_text' into paragraphs.

'structured_text' -- A string consisting of structured text.

returns -- A sequence of pagraphs of structured text. Each element in the sequence corresponds to a successive pagraph in the 'structured_text'. If 'structured_text' is the empty string, the sequence returned will consist of a single paragraph, itself empty.

get_first_paragraph(structured_text)

source code 

Return the first paragraph of 'structured_text'.

'structured_text' -- A string consisting of structured text.

returns -- A string of structured text that is the first paragraph of the 'structured_text'.


Variables Details [hide private]

html_help_text

Value:
'''
<h4>Structured Text</h4>

<p>Structured text is a simple set of conventions for formatting
ordinary text.  Usually, you can simply type ordinary text where QM
expects structured text; the resulting output will be line-wrapped, wi\
th
paragraph breaks indicated by blank lines.</p>
...

__entity_char_regex

Value:
re.compile(r'[\xe5>\xa5\xf2\xc8\xd1\xdd\xe6\xe4\xc2<\xce\xf4\xb8\xca\x\
ac&\xc6\xf8\xb4\xab\xad\xcc\xae\xd2\xa0\xc4\xc3\xd5\xdf\xe0\xd4\xbc\xe\
8\xa1\xbd\xaa\xdc\xf1\xde\xff\xc9\xea\xc5\xbe\xd9\xc0\xf0\xef\xf7\xd6\\
xec\xf5\xd3\xd0\xb1\xcb\xb9\xb2\xb3\xd8\xc1\xa2\xeb\xa6\xed\xb6\xb5\xf\
c\xee\xa9\xcf\xe7\xdb\xb0\xa3\xa4\xfb\xf9\xd7\xe3"\xda\xbf\xfd\xfa\xa7\
\xaf\xc7\xba\xe1\xe9\xb7\xcd\xa8\xfe\xf6\xbb\xe2\xf3]')

_verbatim_regexp

Value:
re.compile(r'(?s)(\'\'\'.*\'\'\')(?:(?:\n *)+\n|\n?$)')

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.ShowItemReportPage-class.html0000664000076400007640000005322011122067151030435 0ustar stefanstefan qm.test.web.web.ShowItemReportPage
Package qm :: Package test :: Package web :: Module web :: Class ShowItemReportPage
[hide private]
[frames] | no frames]

Class ShowItemReportPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
    QMTestReportPage --+
                       |
                      ShowItemReportPage

DTML page for showing tests and resources.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, item, type, field_errors={})
Construct a new DTML context.
source code
 
GetTitle(self)
Return the page title for this page.
source code
 
FormatFieldValue(self, field)
Return an HTML rendering of the value for 'field'.
source code
 
GetClassDescription(self)
Return a full description of the test or resource class.
source code
 
GetBriefClassDescription(self)
Return a brief description of the test or resource class.
source code
 
MakeShowUrl(self)
Return the URL for showing this item.
source code
 
GetDetailUrl(self, test_run)
Return the detail URL for a test.
source code
 
GetResults(self, key=None)
Return the results from all runs that correpond to the current id.
source code

Inherited from QMTestReportPage: FormatTimeIso, GenerateHtmlHeader, GenerateStartBody, GetResultURL, GetRunDatabase

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, item, type, field_errors={})
(Constructor)

source code 

Construct a new DTML context.

These parameters are also available in DTML under the same name:

'server' -- The 'QMTestServer' creating this page.

'item' -- The 'TestDescriptor' or 'ResourceDescriptor' for the test being shown.

'type' -- Either "test" or "resource".

'field_errors' -- A map from field names to corresponding error messages.

Overrides: web.DtmlPage.__init__

GetClassDescription(self)

source code 

Return a full description of the test or resource class.

returns -- The description, formatted as HTML.

GetBriefClassDescription(self)

source code 

Return a brief description of the test or resource class.

returns -- The brief description, formatted as HTML.

GetDetailUrl(self, test_run)

source code 

Return the detail URL for a test.

'test_id' -- The name of the test.

returns -- The URL that contains details about the 'test_id'.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test.Test-class.html0000664000076400007640000006120711122067151025256 0ustar stefanstefan qm.test.test.Test
Package qm :: Package test :: Module test :: Class Test
[hide private]
[frames] | no frames]

Class Test

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
      runnable.Runnable --+
                          |
                         Test

A 'Test' is run to check for correct behavior.

A 'Test' performs some check on the system being tested, and indicates whether the check was successful, or whether the check failed.

Each test class (i.e., class derived from 'Test') describes a set of "arguments". Each argument has a name and a type. The values of these arguments determine the design-time parameters for the test. For example, for a test class that executes program and checks their exit codes, the arguments might consist of the name of the program to execute, and the command-line arguments that should be given to that program. QMTest uses the arguments to prompt the user when creating a new test.

Each test class also defines a 'Run' method that indicates how to run tests in that class. The 'Run' method is responsible for actually performing the test and for reporting the results.

'Test' is an abstract class.

You can extend QMTest by providing your own test class implementation. If the test classes that come with QMTest cannot be used conveniently with your application domain, or if you would like to report more detailed information about passing and failing tests, you may wish to create a new test class.

To create your own test class, you must create a Python class derived (directly or indirectly) from 'Test'. The documentation for each method of 'Test' indicates whether you must override it in your test class implementation. Some methods may be overridden, but do not need to be. You might want to override such a method to provide a more efficient implementation, but QMTest will work fine if you just use the default version.

If QMTest calls a method on a test and that method raises an exception that is not caught within the method itself, QMTest will catch the exception and continue processing.

Nested Classes [hide private]
  OutcomeField
An 'OutcomeField' contains an outcome.
  TestField
A 'TestField' contains the name of a test.

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code
 
GetTargetGroup(self)
Returns the pattern for the targets that can run this test.
source code

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.test.test.TargetGroupField'> target_g...
A list of the arguments to the extension class.
  kind = 'test'
A string giving kind of extension is implemented by the class.
  PREREQUISITES_FIELD_ID = 'prerequisites'
The name of the field that contains the prerequisites on which this test depends.
  _argument_dictionary = {'prerequisites': <<class 'qm.fields.Se...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.SetField'> prerequisites>...
A list of all the 'Field's in this class.
  prerequisites = []
  target_group = '.*'

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

GetTargetGroup(self)

source code 

Returns the pattern for the targets that can run this test.

returns -- A regular expression (represented as a string) that indicates the targets on which this test can be run. If the pattern matches a particular group name, the test can be run on targets in that group.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[<<class 'qm.test.test.TargetGroupField'> target_group>,
 <<class 'qm.fields.SetField'> prerequisites>]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'prerequisites': <<class 'qm.fields.SetField'> prerequisites>,
 'resources': <<class 'qm.fields.SetField'> resources>,
 'target_group': <<class 'qm.test.test.TargetGroupField'> target_group\
>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.SetField'> prerequisites>,
 <<class 'qm.test.test.TargetGroupField'> target_group>,
 <<class 'qm.fields.SetField'> resources>]

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.python_label-module.html0000664000076400007640000000214011122067144030431 0ustar stefanstefan python_label

Module python_label


Classes

PythonLabel

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.reader_test_run.ReaderTestRun-class.html0000664000076400007640000004255311122067150031276 0ustar stefanstefan qm.test.reader_test_run.ReaderTestRun
Package qm :: Package test :: Module reader_test_run :: Class ReaderTestRun
[hide private]
[frames] | no frames]

Class ReaderTestRun

source code

      object --+    
               |    
test_run.TestRun --+
                   |
                  ReaderTestRun

A 'ReaderTestRun' reads its results using a 'ResultReader'.

A 'ResultReader' provides an iterative interface for reading results. A 'ReaderTestRun' uses a 'ResultReader' to populate a dictionary storing all the results from the reader.

Instance Methods [hide private]
 
__init__(self, reader)
Create a new 'ReaderTestRun'
source code
 
GetResult(self, id, kind='test')
Return the 'Result' for the indicated test.
source code
 
GetAnnotation(self, key)
Return the annotation associated with 'key'.
source code
 
GetAnnotations(self)
Return this run's dictionary of annotations.
source code
 
GetAllResults(self, directory='', kind='test')
Return 'Result's from the given directory..
source code

Inherited from test_run.TestRun: CountOutcomes, GetResultsByOutcome

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, reader)
(Constructor)

source code 

Create a new 'ReaderTestRun'

'reader' -- The 'ResultReader' from which we are to read results.

Overrides: object.__init__

GetResult(self, id, kind='test')

source code 

Return the 'Result' for the indicated test.

'id' -- The name of a test or resource.

'kind' -- The kind of result to retrieve. See 'Result' for a list of the available result kinds.

returns -- The 'Result' corresponding to 'test_id'.

raises -- 'KeyError' if there is no result of the given 'kind' for 'id' in the test run.

Overrides: test_run.TestRun.GetResult
(inherited documentation)

GetAnnotation(self, key)

source code 

Return the annotation associated with 'key'.

'key' -- A string giving the name of an annotation.

returns -- A string giving the value of the annotation, or 'None' if there is no such annotation.

Overrides: test_run.TestRun.GetAnnotation
(inherited documentation)

GetAnnotations(self)

source code 

Return this run's dictionary of annotations.

returns -- A dictionary mapping annotation names (strings) to values (also strings).

Overrides: test_run.TestRun.GetAnnotations
(inherited documentation)

GetAllResults(self, directory='', kind='test')

source code 

Return 'Result's from the given directory..

'directory' -- A path to a directory in the test database.

'kind' -- The kind of results to return.

returns -- All the results within 'directory' (including its subdirectories).

Overrides: test_run.TestRun.GetAllResults
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_engine-module.html0000664000076400007640000001167711122067145027102 0ustar stefanstefan qm.test.execution_engine
Package qm :: Package test :: Module execution_engine
[hide private]
[frames] | no frames]

Module execution_engine

source code

Classes [hide private]
  TerminationRequested
A target requested termination of the test loop.
  ExecutionEngine
A 'ExecutionEngine' executes tests.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.VSEval.Eval-class.html0000664000076400007640000002415611122067146031531 0ustar stefanstefan qm.external.DocumentTemplate.VSEval.Eval
Package qm :: Package external :: Package DocumentTemplate :: Module VSEval :: Class Eval
[hide private]
[frames] | no frames]

Class Eval

source code

Known Subclasses:

Provide a very-safe environment for evaluating expressions

This class lets you overide operations, __power__, __mul__, __div__, __mod__, __add__, __sub__, __getitem__, __lshift__, __rshift__, __and__, __xor__, __or__,__pos__, __neg__, __not__, __repr__, __invert__, and __getattr__.

For example, __mult__ might be overridden to prevent expressions like:

 'I like spam' * 100000000

or to disallow or limit attribute access.

Instance Methods [hide private]
 
__init__(self, expr, globals={'__builtins__': {}, '__guarded_getattr__': <function <lambda>...)
Create a 'safe' expression
source code
 
eval(self, mapping) source code
 
__call__(self, **kw) source code
Method Details [hide private]

__init__(self, expr, globals={'__builtins__': {}, '__guarded_getattr__': <function <lambda>...)
(Constructor)

source code 
Create a 'safe' expression

where:

  expr -- a string containing the expression to be evaluated.

  globals -- A global namespace.


qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-T.html0000664000076400007640000005012011122067144024306 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

T



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.directory_suite-module.html0000664000076400007640000001116511122067145026757 0ustar stefanstefan qm.test.directory_suite
Package qm :: Package test :: Module directory_suite
[hide private]
[frames] | no frames]

Module directory_suite

source code

Classes [hide private]
  DirectorySuite
A 'DirectorySuite' is a suite corresponding to a directory.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.ResultPage-class.html0000664000076400007640000003531711122067151026767 0ustar stefanstefan qm.test.web.web.ResultPage
Package qm :: Package test :: Package web :: Module web :: Class ResultPage
[hide private]
[frames] | no frames]

Class ResultPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      ResultPage

DTML page for showing result detail.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, result)
Construct a new 'ResultPage'
source code
 
GetResultURL(self, id) source code
 
GetRunURL(self) source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, result)
(Constructor)

source code 

Construct a new 'ResultPage'

'server' -- The 'QMTestServer' creating this page.

'result' -- The result to display.

Overrides: web.DtmlPage.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command.build_extensions-pysrc.html0000664000076400007640000005335111122067154030377 0ustar stefanstefan qm.dist.command.build_extensions
Package qm :: Package dist :: Package command :: Module build_extensions
[hide private]
[frames] | no frames]

Source Code for Module qm.dist.command.build_extensions

 1  ######################################################################## 
 2  # 
 3  # File:   build_extensions.py 
 4  # Author: Stefan Seefeld 
 5  # Date:   2005-11-16 
 6  # 
 7  # Contents: 
 8  #   Command to build qmtest extensions. 
 9  # 
10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  import qm.xmlutil 
21  from distutils.command.build_py import build_py 
22  from distutils.util import get_platform 
23  import os, sys, dircache 
24   
25  ######################################################################## 
26  # Classes 
27  ######################################################################## 
28   
29 -class build_extensions(build_py):
30 """build extension files.""" 31 32 description = "build qmtest extension classes." 33
34 - def finalize_options(self):
35 36 b = self.distribution.get_command_obj('build') 37 b.ensure_finalized() 38 base = b.build_base 39 40 build_py.finalize_options(self) 41 42 self.build_dir = os.path.join(base, 'ext') 43 if self.distribution.ext_modules: 44 plat_specifier = ".%s-%s" % (get_platform(), sys.version[0:3]) 45 self.build_dir += plat_specifier 46 47 48 self.extensions = self.distribution.qmtest_extensions
49 50
51 - def get_input(self):
52 """Return all files containing extension classes.""" 53 54 files = [os.path.join(self.extensions, f) 55 for f in dircache.listdir(self.extensions) 56 if f.endswith('.py') or f == 'classes.qmc'] 57 return files
58 59
60 - def run(self):
61 62 self.mkpath(self.build_dir) 63 for f in self.get_input(): 64 basename = os.path.basename(f) 65 self.copy_file(f, os.path.join(self.build_dir, basename), 66 preserve_mode=0)
67

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.db-pysrc.html0000664000076400007640000006501511122067154023027 0ustar stefanstefan qm.db
Package qm :: Module db
[hide private]
[frames] | no frames]

Source Code for Module qm.db

  1  ######################################################################## 
  2  # 
  3  # File:   db.py 
  4  # Author: Nathaniel Smith <njs@codesourcery.com 
  5  # Date:   2003-06-13 
  6  # 
  7  # Contents: 
  8  #   A few simple functions to help with connecting to SQL databases 
  9  #   and using the DB 2.0 API. 
 10  # 
 11  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
 12  # 
 13  # For license terms see the file COPYING. 
 14  # 
 15  ######################################################################## 
 16   
 17  ######################################################################## 
 18  # Imports 
 19  ######################################################################## 
 20   
 21  import os 
 22   
 23  ######################################################################## 
 24  # Classes 
 25  ######################################################################## 
 26   
27 -class Connection:
28 """A wrapper around a DB 2.0 connection. 29 30 Provides a minimal but consistent interface to an underlying 31 database connection. In particular, a 'Connection' quotes SQL 32 queries as necessary for the underlying DB 2.0 connection.""" 33
34 - def __init__(self, module_name, *args, **more_args):
35 """Uses the given DB 2.0 module to connect to a database. 36 37 'module_name' -- The DB 2.0-compliant module to use to connect, 38 for example "pgdb". 39 40 'args' -- Positional arguments to pass to the module's 'connect' 41 method. 42 43 'more_args' -- Keyword arguments to pass to the module's 44 'connect' method.""" 45 46 # Last argument must be a non-empty list or __import__ will 47 # return the wrong module. 48 self._module = __import__(module_name, 49 globals(), 50 locals(), 51 [""]) 52 self._connection = self._module.connect(*args, **more_args)
53 54
55 - def close(self):
56 57 self._connection.close()
58 59
60 - def commit(self):
61 62 self._connection.commit()
63 64
65 - def rollback(self):
66 67 self._connection.rollback()
68 69
70 - def execute(self, sql):
71 """Execute a SQL statement in this database. 72 73 If this database requires any overall quoting of the given SQL 74 (for instance, doubling of %'s), it will be performed by this 75 method. 76 77 returns -- A database cursor. 78 79 """ 80 81 # According to the DB 2.0 spec, the following lines should be 82 # necessary. But in fact it seems that the database modules we 83 # use do not strip doubled %'s inside SQL string constants, and 84 # do not try to expand parameters inside SQL string constants. 85 # Since string constants are the main place where %'s may occur, 86 # we do not quote %'s at all. 87 #if self._module.paramstyle in ["format", "pyformat"]: 88 # sql = sql.replace("%", "%%") 89 cursor = self._connection.cursor() 90 91 cursor.execute(sql) 92 return cursor
93 94 95 ######################################################################## 96 # Functions 97 ######################################################################## 98
99 -def quote_string(string):
100 """Quotes a string for SQL. 101 102 'string' -- A string whose contents are to be used in an SQL literal 103 string. 104 105 returns -- A SQL literal string whose contents match that of 106 'string'.""" 107 108 # Replace each ' with '', then surround with more 's. Also double 109 # backslashes. It'd be nice to handle things like quoting non-ASCII 110 # characters (by replacing them with octal escapes), but we don't. 111 return "'" + string.replace("'", "''").replace("\\", "\\\\") + "'"
112 113 ######################################################################## 114 # Local Variables: 115 # mode: python 116 # indent-tabs-mode: nil 117 # fill-column: 72 118 # End: 119

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.DefaultDatabase-class.html0000664000076400007640000002247311122067151026373 0ustar stefanstefan qm.user.DefaultDatabase
qm :: user :: DefaultDatabase :: Class DefaultDatabase
[hide private]
[frames] | no frames]

Class DefaultDatabase

source code

Instance Methods [hide private]
 
GetDefaultUserId(self) source code
 
keys(self) source code
 
__getitem__(self, user_id) source code
 
get(self, user_id, default=None) source code
 
GetGroupIds(self) source code
 
GetGroup(self, group_id) source code
Class Variables [hide private]
  default_user = User("default_user", "default")
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user.XmlDatabaseError-class.html0000664000076400007640000001451711122067151026561 0ustar stefanstefan qm.user.XmlDatabaseError
qm :: user :: XmlDatabaseError :: Class XmlDatabaseError
[hide private]
[frames] | no frames]

Class XmlDatabaseError

source code

              object --+        
                       |        
exceptions.BaseException --+    
                           |    
        exceptions.Exception --+
                               |
                              XmlDatabaseError

Instance Methods [hide private]

Inherited from exceptions.Exception: __init__, __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database-pysrc.html0000664000076400007640000137305711122067155025176 0ustar stefanstefan qm.test.database
Package qm :: Package test :: Module database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.database

   1  ######################################################################## 
   2  # 
   3  # File:   database.py 
   4  # Author: Mark Mitchell 
   5  # Date:   2001-10-05 
   6  # 
   7  # Contents: 
   8  #   QMTest database class. 
   9  # 
  10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
  11  # 
  12  # For license terms see the file COPYING. 
  13  # 
  14  ######################################################################## 
  15   
  16  ######################################################################## 
  17  # imports 
  18  ######################################################################## 
  19   
  20  import os.path 
  21  import qm 
  22  from   qm.common import * 
  23  import qm.extension 
  24  import qm.fields 
  25  from   qm.label import * 
  26  from   qm.test.base import * 
  27  from   qm.test.directory_suite import DirectorySuite 
  28  from   qm.test.runnable import Runnable 
  29  from   qm.test.resource import Resource 
  30  from   qm.test.suite import Suite 
  31  from   qm.test.test import Test 
  32   
  33  ######################################################################## 
  34  # Variables 
  35  ######################################################################## 
  36   
  37  __the_database = None 
  38  """The global 'Database' object.""" 
  39  __the_db_path = '.' 
  40  """The path to the database.""" 
  41   
  42  ######################################################################## 
  43  # Classes 
  44  ######################################################################## 
  45   
46 -class ItemDescriptor:
47 """An 'ItemDescriptor' describes a test, resource, or similar entity. 48 49 Some 'Database' operations return an instance of a class derived 50 from 'ItemDescriptor', rather than the object described. For 51 example, 'Database.GetTest' returns a 'TestDescriptor', not a 52 'Test'. This additional indirection is an optimization; the 53 creation of the actual 'Test' object may be relatively expensive, 54 and in many cases all that is needed is information that can be 55 gleaned from the descriptor.""" 56
57 - def __init__(self, 58 database, 59 instance_id, 60 class_name = None, 61 arguments = None, 62 item = None):
63 """Construct an 'ItemDescriptor'. 64 65 'database' -- The 'Database' object in which this entity is 66 located. 67 68 'instance_id' -- The label for this entity. 69 70 'class_name' -- The name of the extension class for the entity. 71 For example, for a 'TestDescriptor', the 'class_name' is the 72 name of the test class. Omit this argument if 'item' is provided. 73 74 'arguments' -- A dictionary mapping argument names to argument 75 values. These arguments will be provided to the extension class 76 when the entity is constructed. Omit this argument if 'item' is 77 provided. 78 79 'item' -- The item class for this item instance.""" 80 81 self.__database = database 82 self.__id = instance_id 83 assert(not item or not class_name) 84 self.__class_name = class_name 85 self.__arguments = arguments 86 self._item = item
87 88
89 - def GetDatabase(self):
90 """Return the 'Database' containing this entity. 91 92 returns -- The 'Database' object in which this entity is 93 located.""" 94 95 return self.__database
96 97
98 - def GetClassName(self):
99 """Return the class name of the entity. 100 101 returns -- The name of the extension class for the entity. For 102 example, for a 'TestDescriptor', this method returns the name of 103 the test class.""" 104 105 if self._item: 106 return self._item.GetClassName() 107 else: 108 return self.__class_name
109 110
111 - def GetClass(self):
112 """Return the class of the entity. 113 114 returns -- The Python class object for the entity. For example, 115 for a 'TestDescriptor', this method returns the test class.""" 116 117 raise NotImplementedError
118 119
120 - def GetClassArguments(self):
121 """Return the arguments specified by the test class. 122 123 returns -- A list of 'Field' objects containing all the 124 arguments in the class hierarchy. 125 126 Derived classes should not override this method.""" 127 128 return qm.extension.get_class_arguments(self.GetClass())
129 130
131 - def GetArguments(self):
132 """Return the entity arguments. 133 134 returns -- A dictionary mapping argument names to argument 135 values. These arguments will be provided to the extension class 136 when the entity is constructed.""" 137 138 if self._item: 139 return self._item.GetExplicitArguments() 140 else: 141 return self.__arguments
142 143
144 - def GetId(self):
145 """Return the label for this entity. 146 147 returns -- The label for this entity.""" 148 149 return self.__id
150 151
152 - def GetItem(self):
153 """Return the entity. 154 155 returns -- An instance of the class returned by 'GetClass'.""" 156 157 if not self._item: 158 extras = { Runnable.EXTRA_ID : self.GetId(), 159 Runnable.EXTRA_DATABASE : self.GetDatabase() } 160 self._item = self.GetClass()(self.GetArguments(), **extras) 161 162 return self._item
163 164
165 - def GetResources(self):
166 """Return the resources required by this item. 167 168 returns -- A sequence of resource names. Each name indicates a 169 resource that must be available to this item.""" 170 171 return self.GetArguments().get(Runnable.RESOURCE_FIELD_ID, [])
172 173 # Helper functions. 174
175 - def _Execute(self, context, result, method):
176 """Execute the entity. 177 178 'context' -- The 'Context' in which the test should be executed, 179 or 'None' if the 'method' does not take a 'Context' argument. 180 181 'result' -- The 'Result' object corresponding to this execution. 182 183 'method' -- The method name of the method on the entity that 184 should be invoked to perform the execution.""" 185 186 # Get the item. 187 item = self.GetItem() 188 methobj = getattr(item, method) 189 # Execute the indicated method. 190 if context is not None: 191 methobj(context, result) 192 else: 193 methobj(result)
194 195 196
197 -class TestDescriptor(ItemDescriptor):
198 """A test instance.""" 199
200 - def __init__(self, 201 database, 202 test_id, 203 test_class_name = None, 204 arguments = None, 205 test = None):
206 """Create a new test instance. 207 208 'database' -- The 'Database' containing this test. 209 210 'test_id' -- The test ID. 211 212 'test_class_name' -- The name of the test class of which this is 213 an instance. Omit this argument if 'test' is provided. 214 215 'arguments' -- This test's arguments to the test class. 216 Omit this argument if 'test' is provided. 217 218 'test' -- The test class of which this is an instance.""" 219 220 # Initialize the base class. 221 ItemDescriptor.__init__(self, database, 222 test_id, test_class_name, arguments, 223 test) 224 225 self.__prerequisites = {} 226 for p, o in \ 227 self.GetArguments().get(Test.PREREQUISITES_FIELD_ID, []): 228 self.__prerequisites[p] = o
229 230
231 - def GetClass(self):
232 """Return the class of the entity. 233 234 returns -- The Python class object for the entity. For example, 235 for a 'TestDescriptor', this method returns the test class.""" 236 237 if self._item: return type(self._item) 238 return get_extension_class(self.GetClassName(), 'test', 239 self.GetDatabase())
240 241
242 - def GetTest(self):
243 """Return the 'Test' object described by this descriptor.""" 244 245 return self.GetItem()
246 247
248 - def GetPrerequisites(self):
249 """Return a map from prerequisite test IDs to required outcomes.""" 250 251 return self.__prerequisites
252 253
254 - def GetTargetGroup(self):
255 """Returns the pattern for the targets that can run this test. 256 257 returns -- A regular expression (represented as a string) that 258 indicates the targets on which this test can be run. If the 259 pattern matches a particular group name, the test can be run 260 on targets in that group.""" 261 262 return self.GetArguments().get("target_group", ".*")
263 264
265 - def Run(self, context, result):
266 """Execute this test. 267 268 'context' -- The 'Context' in which the test should be executed. 269 270 'result' -- The 'Result' object for this test.""" 271 272 self._Execute(context, result, "Run")
273 274 275
276 -class ResourceDescriptor(ItemDescriptor):
277 """A resource instance.""" 278
279 - def __init__(self, 280 database, 281 resource_id, 282 resource_class_name = None, 283 arguments = None, 284 resource = None):
285 """Create a new resource instance. 286 287 'database' -- The 'Database' containing this resource. 288 289 'resource_id' -- The resource ID. 290 291 'resource_class_name' -- The name of the resource class of which 292 this is an instance. Omit this argument if 'resource' is provided. 293 294 'arguments' -- This resource's arguments to the resource class. 295 Omit this argument if 'resource' is provided. 296 297 'resource' -- The resource class of which this is an instance.""" 298 299 # Initialize the base class. 300 ItemDescriptor.__init__(self, database, resource_id, 301 resource_class_name, arguments, 302 resource)
303 304
305 - def GetClass(self):
306 """Return the class of the entity. 307 308 returns -- The Python class object for the entity. For example, 309 for a 'TestDescriptor', this method returns the test class.""" 310 311 if self._item: return type(self._item) 312 return get_extension_class(self.GetClassName(), 'resource', 313 self.GetDatabase())
314 315
316 - def GetResource(self):
317 """Return the 'Resource' object described by this descriptor.""" 318 319 return self.GetItem()
320 321
322 - def SetUp(self, context, result):
323 """Set up the resource. 324 325 'context' -- The 'Context' in which the resource should be executed. 326 327 'result' -- The 'Result' object for this resource.""" 328 329 self._Execute(context, result, "SetUp")
330 331
332 - def CleanUp(self, result):
333 """Clean up the resource. 334 335 'result' -- The 'Result' object for this resource.""" 336 337 self._Execute(None, result, "CleanUp")
338 339 340
341 -class DatabaseError(QMException):
342 """An exception relating to a 'Database'. 343 344 All exceptions raised directly by 'Database', or its derived 345 classes, will be instances of 'DatabaseError', or a class derived 346 from 'DatabaseError'. 347 348 If QMTest catches the exception, it will treat the string 349 representation of the exception as an error message to be formatted 350 for the user."""
351 352
353 -class NoSuchItemError(DatabaseError):
354 """An exception indicating that a particular item could not be found.""" 355
356 - def __init__(self, kind, item_id):
357 358 self.kind = kind 359 self.item_id = item_id
360 361
362 - def __str__(self):
363 """Return a string describing this exception.""" 364 365 return qm.message("no such item", 366 kind = self.kind, 367 item_id = self.item_id)
368 369 370
371 -class NoSuchTestError(NoSuchItemError):
372 """The specified test does not exist.""" 373
374 - def __init__(self, test_id):
375 """Construct a new 'NoSuchTestError' 376 377 'test_id' -- The name of the test that does not exist.""" 378 379 NoSuchItemError.__init__(self, Database.TEST, test_id)
380 381 382
383 -class NoSuchSuiteError(NoSuchItemError):
384 """The specified suite does not exist.""" 385
386 - def __init__(self, suite_id):
387 """Construct a new 'NoSuchSuiteError' 388 389 'suite_id' -- The name of the suite that does not exist.""" 390 391 NoSuchItemError.__init__(self, Database.SUITE, suite_id)
392 393 394
395 -class NoSuchResourceError(NoSuchItemError):
396 """The specified resource does not exist.""" 397
398 - def __init__(self, resource_id):
399 """Construct a new 'NoSuchResourceError' 400 401 'resource_id' -- The name of the resource that does not exist.""" 402 403 NoSuchItemError.__init__(self, Database.RESOURCE, resource_id)
404 405 406
407 -class Database(qm.extension.Extension):
408 """A 'Database' stores tests, testsuites, and resources. 409 410 A 'Database' has two primary functions: 411 412 1. Test storage and retrieval. 413 414 Every test has a unique name, called a "test id". When a new 415 test is created, the 'Database' is responsible for writing that 416 test to permanent storage. Later, QMTest will request the test 417 by providing the database with the test id. The database must 418 retrieve the test from permanent storage. 419 420 QMTest does not put any restrictions on *how* tests are stored. 421 The default database implementation uses XML to store tests, 422 but any storage format will do. 423 424 2. Test enumeration. 425 426 The 'Database' can tell QMTest what tests are stored in the 427 database. QMTest uses this information in its graphical user 428 interface to show the user what tests exist. 429 430 A 'Database' stores testsuites and resources in addition to tests. 431 The names for tests, testsuites, and resources are all "labels". A 432 label is a special kind of string that is designed to be easily 433 convertible to a file name. For more information, see the 434 'qm.label' module. The namespaces for tests, testsuites, and 435 resources are all distinct. For example, it is OK to have a test 436 with the same name as a testsuite. 437 438 Every 'Database' is associated with a particular directory on the 439 local machine. In most cases, the 'Database' will store all the 440 files it needs within this directory. 441 442 Every 'Database' has an associated 'AttachmentStore'. An 443 'AttachmentStore' is responsible for storing the attachments 444 associated with tests. See the module 'qm.attachment' for more 445 information about 'AttachmentStore'. 446 447 'Database' is an abstract class. 448 449 You can extend QMTest by providing your own database implementation. 450 One reason to do this is that you may want to store tests in a 451 format different from the XML format that QMTest uses by default. 452 For example, if you are testing a compiler, you might want to 453 represent each test as a source file. Or, if you are testing a 454 SQL database, you might want to represent each test as two files: 455 one containing SQL commands to run the test, and one containing 456 the output you expect. 457 458 Another reason to provide your own database implementation is that 459 you might want to store tests on a remote location. For example, 460 suppose you wanted to allow multiple users to access the same 461 central test database. You could create a test database that 462 created and retrieved tests by communicating with the central 463 server. 464 465 To create your own database implementation, you must create a Python 466 class derived (directly or indirectly) from 'Database'. The 467 documentation for each method of 'Database' indicates whether you 468 must override it in your database implementation. Some methods may 469 be overridden, but do not need to be. You might want to override 470 such a method to provide a more efficient implementation, but QMTest 471 will work fine if you just use the default version. 472 473 If QMTest calls a method on a database and that method raises an 474 exception that is not caught within the method itself, QMTest will 475 catch the exception and continue processing. Therefore, methods 476 here only have to handle exceptions themselves if that is necessary 477 to maintain the integrity of the database. 478 479 A single 'Database' may be accessed by multiple threads 480 simultaneously. Therefore, you must take appropriate steps to 481 ensure thread-safe access to shared data.""" 482 483 arguments = [ 484 qm.fields.TextField( 485 name = "label_class", 486 title = "Label Class", 487 description = """The name of the label class used by this database. 488 489 The label class is used to separate names of entities used 490 by the database into directories and basenames.""", 491 default_value = "python_label.PythonLabel" 492 ), 493 qm.fields.BooleanField( 494 name = "modifiable", 495 title = "Modifiable?", 496 description = """Whether or not the database can be modified. 497 498 If true, changes (such as the addition or removal of tests, 499 resources, or suites) can be made to the test database. 500 If false, tests can be viewed and run, but not modified.""", 501 default_value = "true") 502 ] 503 504 RESOURCE = "resource" 505 SUITE = "suite" 506 TEST = "test" 507 508 ITEM_KINDS = [RESOURCE, SUITE, TEST] 509 """The kinds of items that can be stored in a 'Database'.""" 510 511 _item_exceptions = { 512 RESOURCE : NoSuchResourceError, 513 SUITE : NoSuchSuiteError, 514 TEST : NoSuchTestError 515 } 516 """The exceptions to be raised when a particular item cannot be found. 517 518 This map is indexed by the 'ITEM_KINDS'; the value indicates the 519 exception class to be used when the indicated kind cannot be found.""" 520 521 _is_generic_database = False 522 """True if this database implements 'GetExtension' as a primitive. 523 524 Databases should implement 'GetExtension' and then override 525 '_is_generic_database', setting it to 'True'. However, legacy 526 databases implemented 'GetTest', 'GetResource', and 'GetSuite' as 527 primivites. These legacy databases should not override 528 '_generic_database'.""" 529 530 kind = "database" 531 """The 'Extension' kind.""" 532
533 - def __init__(self, path, arguments = None, **args):
534 """Construct a 'Database'. 535 536 'path' -- A string containing the absolute path to the directory 537 containing the database. 538 539 'arguments' -- A dictionary mapping attribute names to values. 540 The use of this parameter is deprecated. Use keyword arguments instead. 541 542 Derived classes must call this method from their own '__init__' 543 methods. Every derived class must have an '__init__' method that 544 takes the path to the directory containing the database as its 545 only argument. The path provided to the derived class '__init__' 546 function will always be an absolute path.""" 547 548 if arguments: args.update(arguments) 549 qm.extension.Extension.__init__(self, **args) 550 551 # The path given must be an absolute path. 552 assert os.path.isabs(path) 553 self.__path = path 554 555 # Translate the label class name into an actual Python class. 556 self.__label_class \ 557 = get_extension_class(self.label_class, "label", self)
558 559 # Methods that deal with labels. 560
561 - def IsValidLabel(self, label, is_component = 1):
562 """Return true if 'label' is valid. 563 564 'label' -- A string that is being considered as a label. 565 566 'is_component' -- True if the string being tested is just a 567 single component of a label path. 568 569 returns -- True if 'label' is a valid name for entities in this 570 database.""" 571 572 return self.__label_class("").IsValid(label, is_component)
573 574
575 - def JoinLabels(self, *labels):
576 """Join the 'labels' together. 577 578 'labels' -- A sequence of strings corresponding to label 579 components. 580 581 returns -- A string containing the complete label.""" 582 583 if not labels: 584 return "" 585 586 return str(apply(self.__label_class(labels[0]).Join, 587 labels[1:]))
588 589
590 - def SplitLabel(self, label):
591 """Split the label into a pair '(directory, basename)'. 592 593 returns -- A pair of strings '(directory, basename)'.""" 594 595 return map(str, self.__label_class(label).Split())
596 597
598 - def SplitLabelLeft(self, label):
599 """Split the label into a pair '(parent, subpath)'. 600 This is the same operation as SplitLabel, except the split 601 occurs at the leftmost separator, not the rightmost, and a 602 single-component label comes back in the parent slot. 603 604 returns -- A pair of strings '(parent, subpath)'.""" 605 606 return map(str, self.__label_class(label).SplitLeft())
607 608
609 - def GetLabelComponents(self, label):
610 """Return all of the component directories of 'label'. 611 612 'label' -- A string naming an entity in the database. 613 614 returns -- A list of strings. The first string is the first 615 directory in 'label'; the last string is the basename.""" 616 617 components = [] 618 while label: 619 dirname, label = self.SplitLabelLeft(label) 620 if dirname: 621 components.append(dirname) 622 else: 623 components.append(label) 624 break 625 626 return components
627 628 629 # Generic methods that deal with extensions. 630
631 - def GetExtension(self, id):
632 """Return the extension object named 'id'. 633 634 'id' -- The label for the extension. 635 636 returns -- The instance of 'Extension' with the indicated name, 637 or 'None' if there is no such entity. 638 639 Database classes should override this method. For backwards 640 compatibility, this base class implements this generic method 641 in terms of the special-purpose methods 'GetTest()' and 'GetResource()'. 642 Only if _is_generic_database is True are these implemented in terms 643 of 'GetExtension()'.""" 644 645 for kind in (Database.TEST, Database.RESOURCE): 646 try: 647 return self.GetItem(kind, id).GetItem() 648 except NoSuchItemError: 649 pass 650 651 try: 652 return self.GetSuite(id) 653 except NoSuchSuiteError: 654 pass 655 656 return None
657 658
659 - def GetExtensions(self, directory, scan_subdirs):
660 """Return the extensions in 'directory'. 661 662 'directory' -- The name of a directory. 663 664 'scan_subdirs' -- True if (and only if) subdirectories of 665 'directory' should be scanned. 666 667 returns -- A dictionary mapping labels to 'Extension' 668 instances. The dictionary contains all extensions in 669 'directory', and, if 'scan_subdirs' is true, its 670 subdirectories.""" 671 672 extensions = {} 673 674 for kind in self.ITEM_KINDS: 675 ids = self.GetIds(kind, directory, scan_subdirs) 676 for id in ids: 677 extensions[id] = self.GetExtension(id) 678 679 return extensions
680 681
682 - def RemoveExtension(self, id, kind):
683 """Remove the extension 'id' from the database. 684 685 'id' -- A label for the 'Extension' instance stored in the 686 database. 687 688 'kind' -- The kind of 'Extension' stored with the given 'id'.""" 689 690 raise NotImplementedError
691 692
693 - def WriteExtension(self, id, extension):
694 """Store 'extension' in the database, using the name 'id'. 695 696 'id' -- A label for the 'extension'. 697 698 'extension' -- An instance of 'Extension'. 699 700 The 'extension' is stored in the database. If there is a 701 previous item in the database with the same id, it is removed 702 and replaced with 'extension'. Some databases may not be able 703 to store all 'Extension' instances; those database must throw an 704 exception when an attempt is made to store such an 705 'extension'.""" 706 707 raise NotImplementedError
708 709 710 # Methods that deal with tests. 711
712 - def GetTest(self, test_id):
713 """Return the 'TestDescriptor' for the test named 'test_id'. 714 715 'test_id' -- A label naming the test. 716 717 returns -- A 'TestDescriptor' corresponding to 'test_id'. 718 719 raises -- 'NoSuchTestError' if there is no test in the database 720 named 'test_id'.""" 721 722 if self._is_generic_database: 723 test = self.GetExtension(test_id) 724 if isinstance(test, Test): 725 return TestDescriptor(self, test_id, test=test) 726 727 raise NoSuchTestError(test_id)
728 729
730 - def HasTest(self, test_id):
731 """Check whether or not the database has a test named 'test_id'. 732 733 'test_id' -- A label naming the test. 734 735 returns -- True if and only if the database contains a test 736 named 'test_id'. If this function returns true, 'GetTest' will 737 usually succeed. However, they may be circumstances where 738 'HasTest' returns true and 'GetTest' does not succeed. For 739 example, someone might remove a critical file from the database 740 between the time that 'HasTest' is called and the time that 741 'GetTest' is called. 742 743 Derived classes may override this method.""" 744 745 try: 746 self.GetTest(test_id) 747 except NoSuchTestError: 748 return 0 749 else: 750 return 1
751 752
753 - def GetTestIds(self, directory="", scan_subdirs=1):
754 """Return all test IDs that begin with 'directory'. 755 756 'directory' -- A label indicating the directory in which to 757 begin the search. 758 759 'scan_subdirs' -- True if (and only if) subdirectories of 760 'directory' should be scanned. 761 762 'returns' -- A list of all tests located within 'directory', 763 as absolute labels.""" 764 765 return self.GetIds(self.TEST, directory, scan_subdirs)
766 767 # Methods that deal with suites. 768
769 - def GetSuite(self, suite_id):
770 """Return the 'Suite' for the suite named 'suite_id'. 771 772 'suite_id' -- A label naming the suite. 773 774 returns -- An instance of 'Suite' (or a derived class of 775 'Suite') corresponding to 'suite_id'. 776 777 raises -- 'NoSuchSuiteError' if there is no test in the database 778 named 'test_id'. 779 780 All databases must have an implicit suite called '' that 781 contains all tests in the database. More generally, for each 782 directory in the database, there must be a corresponding suite 783 that contains all tests in that directory and its 784 subdirectories.""" 785 786 if suite_id == "": 787 return DirectorySuite(self, "") 788 789 if self._is_generic_database: 790 suite = self.GetExtension(suite_id) 791 if isinstance(suite, Suite): 792 return suite 793 794 raise NoSuchSuiteError(suite_id)
795 796
797 - def HasSuite(self, suite_id):
798 """Check whether or not the database has a suite named 'suite_id'. 799 800 'suite_id' -- A label naming the suite. 801 802 returns -- True if and only if the database contains a suite 803 named 'suite_id'. If this function returns true, 'GetSuite' 804 will usually succeed. However, they may be circumstances where 805 'HasSuite' returns true and 'GetSuite' does not succeed. For 806 example, someone might remove a critical file from the database 807 between the time that 'HasSuite' is called and the time that 808 'GetSuite' is called. 809 810 All databases must have an implicit suite called "" that 811 contains all tests in the database. More generally, for each 812 directory in the database, there must be a corresponding suite 813 that contains all tests in that directory and its 814 subdirectories. 815 816 Derived classes may override this method.""" 817 818 try: 819 self.GetSuite(suite_id) 820 except NoSuchSuiteError: 821 return 0 822 else: 823 return 1
824 825
826 - def GetSuiteIds(self, directory="", scan_subdirs=1):
827 """Return all suite IDs that begin with 'directory'. 828 829 'directory' -- A label indicating the directory in which to 830 begin the search. 831 832 'scan_subdirs' -- True if (and only if) subdirectories of 833 'directory' should be scanned. 834 835 'returns' -- A list of all suites located within 'directory', 836 as absolute labels.""" 837 838 return self.GetIds(self.SUITE, directory, scan_subdirs)
839 840 841 # Methods that deal with resources. 842
843 - def GetResource(self, resource_id):
844 """Return the 'ResourceDescriptor' for the resource 'resouce_id'. 845 846 'resource_id' -- A label naming the resource. 847 848 returns -- A 'ResourceDescriptor' corresponding to 'resource_id'. 849 850 raises -- 'NoSuchResourceError' if there is no resource in the 851 database named 'resource_id'.""" 852 853 if self._is_generic_database: 854 resource = self.GetExtension(resource_id) 855 if isinstance(resource, Resource): 856 return ResourceDescriptor(self, resource_id, resource = resource) 857 858 raise NoSuchResourceError(resource_id)
859 860
861 - def HasResource(self, resource_id):
862 """Check whether or not the database has a resource named 863 'resource_id'. 864 865 'resource_id' -- A label naming the resource. 866 867 returns -- True if and only if the database contains a resource 868 named 'resource_id'. If this function returns true, 869 'GetResource' will usually succeed. However, they may be 870 circumstances where 'HasResource' returns true and 'GetResource' 871 does not succeed. For example, someone might remove a critical 872 file from the database between the time that 'HasResource' is 873 called and the time that 'GetResource' is called. 874 875 Derived classes may override this method.""" 876 877 try: 878 self.GetResource(resource_id) 879 except NoSuchResourceError: 880 return 0 881 else: 882 return 1
883 884
885 - def GetResourceIds(self, directory="", scan_subdirs=1):
886 """Return all resource IDs that begin with 'directory'. 887 888 'directory' -- A label indicating the directory in which to 889 begin the search. 890 891 'scan_subdirs' -- True if (and only if) subdirectories of 892 'directory' should be scanned. 893 894 'returns' -- A list of all resources located within 'directory', 895 as absolute labels.""" 896 897 return self.GetIds(self.RESOURCE, directory, scan_subdirs)
898 899 # Miscellaneous methods. 900
901 - def GetIds(self, kind, directory = "", scan_subdirs = 1):
902 """Return all IDs of the indicated 'kind' that begin with 'directory'. 903 904 'kind' -- One of the 'ITEM_KINDS'. 905 906 'directory' -- A label indicating the directory in which to 907 begin the search. 908 909 'scan_subdirs' -- True if (and only if) subdirectories of 910 'directory' should be scanned. 911 912 returns -- A list of all items of the indicated 'kind' located 913 within 'directory', as absolute labels. 914 915 Derived classes may override this method.""" 916 917 if self._is_generic_database: 918 extensions = self.GetExtensions(directory, scan_subdirs) 919 extensions = filter(lambda e: e.kind == kind, 920 extensions.values()) 921 return map(lambda e: e.GetId(), extensions) 922 923 return []
924 925
926 - def GetItem(self, kind, item_id):
927 """Return the item of the indicated 'kind' with indicated 'item_id'. 928 929 'kind' -- One of the 'ITEM_KINDS'. 930 931 'item_id' -- The name of the item. 932 933 returns -- If 'kind' is 'Database.TEST' or 'Database.RESOURCE', 934 returns a test descriptor or resource descriptor, respectively. 935 If 'kind' is 'Database.SUITE', returns a 'Suite'. 936 937 Derived classes may override this method.""" 938 939 return { Database.TEST : self.GetTest, 940 Database.RESOURCE : self.GetResource, 941 Database.SUITE : self.GetSuite } [kind] (item_id)
942 943 944
945 - def GetSubdirectories(self, directory):
946 """Return the immediate subdirectories of 'directory'. 947 948 'directory' -- A label indicating a directory in the database. 949 950 returns -- A sequence of (relative) labels indictating the 951 immediate subdirectories of 'directory'. For example, if "a.b" 952 and "a.c" are directories in the database, this method will 953 return "b" and "c" given "a" as 'directory'. 954 955 Derived classes may override this method.""" 956 957 return []
958 959
960 - def GetPath(self):
961 """Return the directory containing the database. 962 963 returns -- A string containing the absolute path to the 964 directory containing the database. 965 966 Derived classes must not override this method.""" 967 968 return self.__path
969 970
971 - def GetConfigurationDirectory(self):
972 """Return the directory containing configuration information. 973 974 returns -- The directory containing configuration information 975 for the database. 976 977 Derived classes must not override this method.""" 978 979 return get_configuration_directory(self.GetPath())
980 981
982 - def GetAttachmentStore(self):
983 """Returns the 'AttachmentStore' associated with the database. 984 985 returns -- The 'AttachmentStore' containing the attachments 986 associated with tests and resources in this database. 987 988 Derived classes may override this method.""" 989 990 return None
991 992
993 - def GetClassPaths(self):
994 """Return directories to search for test and resource classes. 995 996 returns -- A sequence of strings. Each string is a directory 997 that should be searched to locate test and resource classes. 998 The directories will be searched in the order they appear. 999 QMTest will search other directories (like those in the 1000 'QMTEST_CLASS_PATH' environment variable) in addition to these 1001 directories. 1002 1003 For a given database, this method should always return the same 1004 value; callers are permitted to cache the value returned. 1005 1006 Derived classes may override this method. The sequence returned 1007 by the derived class need not be a superset of the value 1008 returned by the default implementation (but probably should 1009 be).""" 1010 1011 return []
1012 1013
1014 - def GetTestClassNames(self):
1015 """Return the kinds of tests that the database can store. 1016 1017 returns -- A sequence of strings. Each string names a 1018 class, including the containing module. Only classes 1019 of these types can be stored in the database. 1020 1021 Derived classes may override this method. The default 1022 implementation allows all available test classes, but the 1023 derived class may allow only a subset.""" 1024 1025 return get_extension_class_names('test', self)
1026 1027
1028 - def GetResourceClassNames(self):
1029 """Return the kinds of resources that the database can store. 1030 1031 returns -- A sequence of strings. Each string names a 1032 class, including the containing module. Only resources 1033 of these types can be stored in the database. 1034 1035 Derived classes may override this method. The default 1036 implementation allows all available resource classes, but the 1037 derived class may allow only a subset.""" 1038 1039 return get_extension_class_names('resource', self)
1040 1041
1042 - def ExpandIds(self, ids):
1043 """Expand test and suite IDs into test IDs. 1044 1045 'ids' -- A sequence of IDs of tests and suites, which may be mixed 1046 together. 1047 1048 returns -- A pair 'test_ids, suite_ids'. 'test_ids' is a 1049 sequence of test IDs including all test IDs mentioned in 'ids' plus 1050 all test IDs obtained from recursively expanding suites included in 1051 'ids'. 'suite_ids' is the set of IDs of suites included directly 1052 and indirectly in 'ids'. 1053 1054 raises -- 'ValueError' if an element in 'id' is neither a test or 1055 suite ID. The exception argument is the erroneous element.""" 1056 1057 # We'll collect test and suite IDs in maps, to make duplicate 1058 # checks efficient. 1059 test_ids = {} 1060 suite_ids = {} 1061 1062 for id in ids: 1063 # Skip this ID if we've already seen it. 1064 if suite_ids.has_key(id) or test_ids.has_key(id): 1065 continue 1066 # Is this a suite ID? 1067 if self.HasSuite(id): 1068 suite_ids[id] = None 1069 # Yes. Load the suite. 1070 suite = self.GetSuite(id) 1071 # Determine all the tests and suites contained directly and 1072 # indirectly in this suite. 1073 suite_test_ids, sub_suite_ids = suite.GetAllTestAndSuiteIds() 1074 # Add them. 1075 for test_id in suite_test_ids: 1076 test_ids[test_id] = None 1077 for suite_id in sub_suite_ids: 1078 suite_ids[suite_id] = None 1079 # Or is this a test ID? 1080 elif self.HasTest(id): 1081 # Yes. Add it. 1082 test_ids[id] = None 1083 else: 1084 # It doesn't look like a test or suite ID. 1085 raise ValueError, id 1086 1087 # Convert the maps to sequences. 1088 return test_ids.keys(), suite_ids.keys()
1089 1090
1091 - def IsModifiable(self):
1092 """Returns true iff this database is modifiable. 1093 1094 returns -- True iff this database is modifiable. If the 1095 database is modifiable, it supports operatings like 'Write' 1096 that make changes to the structure of the databaes itself. 1097 Otherwise, the contents of the database may be viewed, but not 1098 modified.""" 1099 1100 return self.modifiable == "true"
1101 1102 ######################################################################## 1103 # Functions 1104 ######################################################################## 1105
1107 """Return the configuration directory for the 'Database' rooted at 'path'. 1108 1109 'path' -- The path to the test database. 1110 1111 returns -- The path to the configuration directory.""" 1112 1113 return os.path.join(path, "QMTest")
1114 1115
1116 -def get_configuration_file(path):
1117 """Return the configuration file for the 'Database' rooted at 'path'. 1118 1119 'path' -- The path to the test database. 1120 1121 returns -- The path to the configuration file.""" 1122 1123 return os.path.join(get_configuration_directory(path), 1124 "configuration")
1125 1126
1127 -def is_database(db_path):
1128 """Returns true if 'db_path' looks like a test database.""" 1129 1130 # A test database is a directory. 1131 if not os.path.isdir(db_path): 1132 return 0 1133 # A test database contains a configuration file. 1134 if not os.path.isfile(get_configuration_file(db_path)): 1135 return 0 1136 # It probably is OK. 1137 return 1
1138 1139
1140 -def load_database(db_path):
1141 """Load the database from 'db_path'. 1142 1143 'db_path' -- The path to the directory containing the database. 1144 1145 returns -- The new 'Database'.""" 1146 1147 # Make sure it is a directory. 1148 if not is_database(db_path): 1149 raise QMException, \ 1150 qm.error("not test database", path=db_path) 1151 1152 # Load the file. 1153 config_path = get_configuration_file(db_path) 1154 document = qm.xmlutil.load_xml_file(config_path) 1155 1156 # Parse it. 1157 database_class, arguments \ 1158 = (qm.extension.parse_dom_element 1159 (document.documentElement, 1160 lambda n: qm.test.base.get_extension_class(n, "database", 1161 None, db_path))) 1162 # For backwards compatibility with QM 1.1.x, we look for "attribute" 1163 # elements. 1164 for node in document.documentElement.getElementsByTagName("attribute"): 1165 name = node.getAttribute("name") 1166 # These elements were only allowed to contain strings as 1167 # values. 1168 value = qm.xmlutil.get_dom_text(node) 1169 # Python does not allow keyword arguments to have Unicode 1170 # values, so we convert the name to an ordinary string. 1171 arguments[str(name)] = value 1172 1173 return database_class(db_path, arguments)
1174 1175 1176 ######################################################################## 1177 # Functions 1178 ######################################################################## 1179
1180 -def set_path(path):
1181 """Set the database path to be used when the database is loaded. 1182 1183 'path' -- A string containing the path to the database.""" 1184 1185 global __the_db_path 1186 1187 __the_db_path = path
1188 1189
1190 -def get_database():
1191 """Returns the global Database object. 1192 1193 returns -- The 'Database' object that corresponds to the currently 1194 executing process. It may be None.""" 1195 1196 global __the_database 1197 1198 if not __the_database: 1199 __the_database = load_database(__the_db_path) 1200 1201 return __the_database
1202 1203 1204 ######################################################################## 1205 # Local Variables: 1206 # mode: python 1207 # indent-tabs-mode: nil 1208 # fill-column: 72 1209 # End: 1210

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.trace.Tracer-class.html0000664000076400007640000003541311122067151024720 0ustar stefanstefan qm.trace.Tracer
Package qm :: Module trace :: Class Tracer
[hide private]
[frames] | no frames]

Class Tracer

source code

A 'Tracer' outputs trace messages useful for debugging.

Instance Methods [hide private]
 
__init__(self, file=sys.stdout)
Construct a new 'Tracer'.
source code
 
Write(self, message, category, level=0)
Output a trace message.
source code
 
GetThreshold(self, category)
Return the current threshold for 'category'.
source code
 
SetThreshold(self, category, level)
Set the threshold associated with 'category'.
source code
Class Variables [hide private]
  prefix = 'QM_THRESHOLD_'
The prefix for an environment variable that indicates a threshold for a particular trace category.
Method Details [hide private]

__init__(self, file=sys.stdout)
(Constructor)

source code 

Construct a new 'Tracer'.

'file' -- The file object to which output should be written.

Write(self, message, category, level=0)

source code 

Output a trace message.

'message' -- A string giving the contents of the message. The message should begin with a capital letter and end with a period.

'category' -- A string indicating the category to which this message belongs.

'level' -- A non-negative integer indicating the level at which the message should be output.

Every category has an associated threshold. If the level of the 'message' is less than the threshold, the mesage will be output.

GetThreshold(self, category)

source code 

Return the current threshold for 'category'.

'category' -- A string giving a trace category.

returns -- The threshold associated with 'category'. If no threshold has been set, the threshold is considered to be zero.

SetThreshold(self, category, level)

source code 

Set the threshold associated with 'category'.

'category' --A string giving a trace category.

'level' -- A non-negative integer indicating the threshold level for 'category'.


Class Variable Details [hide private]

prefix

The prefix for an environment variable that indicates a threshold for a particular trace category. The string following the prefix gives the name of the trace category. If the environment variable has no associated level, the associated level is one. Otherwise, the associated level is given by the value of the environment variable.

Value:
'QM_THRESHOLD_'

././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.text_result_stream.TextResultStream-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.text_result_stream.TextResultStream-class.0000664000076400007640000010447011122067147033370 0ustar stefanstefan qm.test.classes.text_result_stream.TextResultStream
Package qm :: Package test :: Package classes :: Module text_result_stream :: Class TextResultStream
[hide private]
[frames] | no frames]

Class TextResultStream

source code

                 object --+            
                          |            
        extension.Extension --+        
                              |        
     result_stream.ResultStream --+    
                                  |    
file_result_stream.FileResultStream --+
                                      |
                                     TextResultStream

A 'TextResultStream' displays test results textually.

A 'TextResultStream' displays information textually, in human readable form. This 'ResultStream' is used when QMTest is run without a graphical user interface.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a 'TextResultStream'.
source code
 
WriteResult(self, result)
Output a test or resource result.
source code
 
Summarize(self)
Output summary information about the results.
source code
 
_DisplayStatistics(self)
Write out statistical information about the results.
source code
 
_SummarizeTestStats(self)
Generate statistics about the overall results.
source code
 
_SummarizeRelativeTestStats(self)
Generate statistics showing results relative to expectations.
source code
 
_FormatStatistics(self, format)
Output statistical information.
source code
 
_SummarizeResults(self, results)
Summarize each of the results.
source code
 
_DisplayResult(self, result, format)
Display 'result'.
source code
 
_DisplayAnnotations(self, result)
Display the annotations associated with 'result'.
source code
 
_WriteOutcome(self, name, kind, outcome, expected_outcome=None)
Write a line indicating the outcome of a test or resource.
source code
 
_DisplayHeading(self, heading)
Display 'heading'.
source code

Inherited from result_stream.ResultStream: WriteAllAnnotations, WriteAnnotation

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.EnumerationField(name= "format", title=...
A list of the arguments to the extension class.

Inherited from file_result_stream.FileResultStream: file, filename

Inherited from result_stream.ResultStream: expected_outcomes, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a 'TextResultStream'.

'args' -- As for 'Extension.__init__'.

Overrides: object.__init__

WriteResult(self, result)

source code 

Output a test or resource result.

'result' -- A 'Result'.

Overrides: result_stream.ResultStream.WriteResult

Summarize(self)

source code 

Output summary information about the results.

When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point.

Overrides: result_stream.ResultStream.Summarize

_DisplayStatistics(self)

source code 

Write out statistical information about the results.

Write out statistical information about the results.

_FormatStatistics(self, format)

source code 

Output statistical information.

'format' -- A format string with (optional) fill-ins corresponding to statistical information.

The formatted string is written to the result file.

_SummarizeResults(self, results)

source code 

Summarize each of the results.

'results' -- The sequence of 'Result' objects to summarize.

_DisplayResult(self, result, format)

source code 

Display 'result'.

'result' -- The 'Result' of a test or resource execution.

'format' -- The format to use when displaying results.

_DisplayAnnotations(self, result)

source code 

Display the annotations associated with 'result'.

'result' -- The 'Result' to dispay.

_WriteOutcome(self, name, kind, outcome, expected_outcome=None)

source code 

Write a line indicating the outcome of a test or resource.

'name' -- The name of the test or resource.

'kind' -- The kind of result being displayed.

'outcome' -- A string giving the outcome.

'expected_outcome' -- If not 'None', the expected outcome.

_DisplayHeading(self, heading)

source code 

Display 'heading'.

'heading' -- The string to use as a heading for the next section of the report.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.EnumerationField(name= "format", title= "Format", descripti\
on= """The output format used by this result stream.

            There are three sections to the output:

            (S) Summary statistics.

            (I) Individual test-by-test results.
...

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_String-module.html0000664000076400007640000000276111122067144032277 0ustar stefanstefan DT_String

Module DT_String


Classes

File
FileMixin
String

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.xml_expectation_database-module.html0000664000076400007640000000223211122067144033002 0ustar stefanstefan xml_expectation_database

Module xml_expectation_database


Classes

XMLExpectationDatabase

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Try-module.html0000664000076400007640000001130611122067145031020 0ustar stefanstefan qm.external.DocumentTemplate.DT_Try
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Try
[hide private]
[frames] | no frames]

Module DT_Try

source code

Classes [hide private]
  Try
Zope DTML Exception handling
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.executable.TimeoutExecutable-class.html0000664000076400007640000005204211122067146030154 0ustar stefanstefan qm.executable.TimeoutExecutable
Package qm :: Module executable :: Class TimeoutExecutable
[hide private]
[frames] | no frames]

Class TimeoutExecutable

source code

object --+    
         |    
Executable --+
             |
            TimeoutExecutable

A 'TimeoutExecutable' runs for a limited time.

If the timer expires, the child process is killed and self.timedout is set to 1. Otherwise, self.timedout is set to 0.

In order to implement this functionality under UNIX, the child process is placed into its own process group. An additional monitoring process is created whose sole job is to kill the primary child's process group if the timeout expires. Process groups are used so that if the child process spawns additional processes they are killed too. A separate monitoring process is used so as not to block the parent.

Under Windows, a monitoring thread is created. When the timer expires, the child process is terminated. However, the child process is not placed into a separate process group, so granchildren kare not terminated. In the future, when Python provides access to 'CreateJobObject' and related functions, jobs will be used to provide functionality similar to UNIX process groups.

The 'Run' method will automatically start the monitoring process. The 'Spawn' method does not start the monitoring process. User's of 'Spawn' should invoke '_DoParent' in order to start the monitoring process. Derived class '_DoParent' functions should call the version defined in this class.

Instance Methods [hide private]
 
__init__(self, timeout=-1)
Construct a new 'TimeoutExecutable'.
source code
 
_InitializeChild(self)
Initialize the child process.
source code
 
_HandleChild(self)
Run in the parent process after the child has been created.
source code
 
Run(self, arguments=[], environment=None, dir=None, path=None)
Spawn the program and wait for it to finish.
source code
 
__UseSeparateProcessGroupForChild(self)
Returns true if the child wil be placed in its own process group.
source code
 
__Monitor(self)
Kill the child if the timeout expires.
source code

Inherited from Executable: Kill, Spawn

Inherited from Executable (private): _DoParent, _GetChildPID, _InitializeParent

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, timeout=-1)
(Constructor)

source code 

Construct a new 'TimeoutExecutable'.

'timeout' -- The number of seconds that the child is permitted to run. This value may be a floating-point value. However, the value may be rounded to an integral value on some systems. Once the timeout expires, the child and its entire process group is killed. (The processes in the process group are sent the 'SIGKILL' signal.) If the 'timeout' is -2, the child is allowed to run forever, but when it terminates the child's process group is killed.

If the 'timeout' is -1, this class behaves exactly like 'Executable'.

Overrides: object.__init__

_InitializeChild(self)

source code 

Initialize the child process.

After 'fork' is called this method is invoked to give the child a chance to initialize itself. '_InitializeParent' will already have been called in the parent process.

This method is not used under Windows.

Overrides: Executable._InitializeChild
(inherited documentation)

_HandleChild(self)

source code 

Run in the parent process after the child has been created.

The child process has been spawned; its PID is avialable via '_GetChildPID'. Take any actions in the parent that are required now that the child exists.

Derived class versions must call this method.

Overrides: Executable._HandleChild
(inherited documentation)

Run(self, arguments=[], environment=None, dir=None, path=None)

source code 

Spawn the program and wait for it to finish.

'arguments' -- The sequence of arguments that should be passed to the executable. The first argument provided in this sequence will be 'argv[0]'.

'environment' -- If not 'None', a dictionary giving the environment that should be provided to the child. If 'None', the child will inherit the parents environment.

'dir' -- If not 'None', the directory in which the child should begin execution. If 'None', the child will execute in the same directory as the parent.

'path' -- If not 'None', the path to the program to run. If 'None', 'arguments[0]' is used.

returns -- The status returned by the program. Under UNIX, this is the value returned by 'waitpid'; under Windows, it is the value returned by 'GetExitCodeProcess'.

After invoking 'Spawn', this function invokes '_DoParent' to allow the parent process to perform whatever actions are required. After that function returns, the parent waits for the child process to exit.

Overrides: Executable.Run
(inherited documentation)

__UseSeparateProcessGroupForChild(self)

source code 

Returns true if the child wil be placed in its own process group.

returns -- True if the child will be placed in its own process group. In that case, a separate monitoring process will also be created.

__Monitor(self)

source code 

Kill the child if the timeout expires.

This function is run in the monitoring thread.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.command.ExecTest-class.html0000664000076400007640000004362311122067146030164 0ustar stefanstefan qm.test.classes.command.ExecTest
Package qm :: Package test :: Package classes :: Module command :: Class ExecTest
[hide private]
[frames] | no frames]

Class ExecTest

source code

         object --+                
                  |                
extension.Extension --+            
                      |            
      runnable.Runnable --+        
                          |        
                  test.Test --+    
                              |    
                   ExecTestBase --+
                                  |
                                 ExecTest

Check a program's output and exit code.

An 'ExecTest' runs a program by using the 'exec' system call.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code

Inherited from ExecTestBase: MakeEnvironment, RunProgram, ValidateOutput

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "program", title= "Prog...
A list of the arguments to the extension class.
  _allow_arg_names_matching_class_vars = 1
True if it is OK for fields to have the same name as class variables.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

Overrides: test.Test.Run

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "program", title= "Program", not_empty_text\
= 1, description= """The path to the program.

            This field indicates the path to the program.  If it is no\
t
            an absolute path, the value of the 'PATH' environment
            variable will be used to search for the program."""), qm.f\
ields.SetField(qm.fields.TextField(name= "arguments", title= "Argument\
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.context.Context-class.html0000664000076400007640000010554011122067150026466 0ustar stefanstefan qm.test.context.Context
Package qm :: Package test :: Module context :: Class Context
[hide private]
[frames] | no frames]

Class Context

source code

object --+    
         |    
      dict --+
             |
            Context

Test-time and local configuration for tests.

A 'Context' object contains all of the information a test needs to
execute, beyond what is stored as part of the test specification
itself.  Information in the context can include,

  * Local (per-user, etc.) configuration, such as where to find the
    tested program.

  * Environmental information, such as which machine the test is
    running on.

  * One-time configuration, including test arguments specified on
    the command line.

A 'Context' object is effectively a mapping object whose keys must
be labels and values must be strings.

Instance Methods [hide private]
new empty dictionary

__init__(self, context=None)
Construct a new context.
source code
 
GetDerivedValue(self, klass, variable, default=None)
Return the value for 'variable' in scope 'klass'.
source code
 
GetBoolean(self, key, default=None)
Return the boolean value associated with 'key'.
source code
 
GetStringList(self, key, default=None)
Return the list of strings associated with 'key'.
source code
 
GetTemporaryDirectory(self)
Return the path to the a temporary directory.
source code
 
Read(self, file_name)
Read the context file 'file_name'.
source code
True if D has a key k, else False
__contains__(self, key) source code
D[k] if k in D, else d
get(self, key, default=None)
d defaults to None.
source code
True if D has a key k, else False
has_key(self, key) source code
 
__getitem__(self, key)
x[y]
source code
list of D's (key, value) pairs, as 2-tuples
items(self) source code
 
GetAddedProperties(self)
Return the properties added to this context by resources.
source code

Inherited from dict: __cmp__, __delitem__, __eq__, __ge__, __getattribute__, __gt__, __hash__, __iter__, __le__, __len__, __lt__, __ne__, __new__, __repr__, __setitem__, clear, copy, fromkeys, iteritems, iterkeys, itervalues, keys, pop, popitem, setdefault, update, values

Inherited from object: __delattr__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]
  TARGET_CONTEXT_PROPERTY = 'qmtest.target'
The context variable giving the name of the current target.
  DB_PATH_CONTEXT_PROPERTY = 'qmtest.dbpath'
The context variable giving the path to the database.
  ID_CONTEXT_PROPERTY = 'qmtest.id'
The context variable giving the name of the running test or resource.
  TMPDIR_CONTEXT_PROPERTY = 'qmtest.tmpdir'
A context property whose value is a string giving the path to a temporary directory.
  __safe_for_unpickling__ = 1
Required to unpickle new-style classes under Python 2.2.
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, context=None)
(Constructor)

source code 

Construct a new context.

'context' -- If not 'None', the existing 'Context' being wrapped by this new context.

Returns:
new empty dictionary

Overrides: object.__init__

GetDerivedValue(self, klass, variable, default=None)

source code 
Return the value for 'variable' in scope 'klass'.
Scopes are nested with '.', and inner variables hide
outer variables of the same name. Thus, looking up the
value of 'a.b.c.var' will return 1 if the context
contains
  a.b.c.var=1
but 2 if it contains
  a.b.d.var=1
  a.b.var=2
  a.var=3.

'klass' -- The variable's scope.

'variable' -- The variable name.

'default' -- Default value.

GetBoolean(self, key, default=None)

source code 

Return the boolean value associated with 'key'.

'key' -- A string.

'default' -- A default boolean value.

returns -- The value associated with 'key' in the context, interpreted as a boolean.

If there is no value associated with 'key' and default is not 'None', then the boolean value associated with default is used. If there is no value associated with 'key' and default is 'None', an exception is raised.

The value associated with 'key' must be a string. If not, an exception is raised. If the value is a string, but does not correspond to a boolean value, an exception is raised.

GetStringList(self, key, default=None)

source code 

Return the list of strings associated with 'key'.

'key' -- A string.

'default' -- A default list.

If there is no value associated with 'key' and default is not 'None', then the boolean value associated with default is used. If there is no value associated with 'key' and default is 'None', an exception is raised.

The value associated with 'key' must be a string. If not, an exception is raised. If the value is a string, but does not correspond to a string list, an exception is raised.

GetTemporaryDirectory(self)

source code 

Return the path to the a temporary directory.

returns -- The path to the a temporary directory. The 'Runnable' object may make free use of this temporary directory; no other 'Runnable's will use the same directory at the same time.

Read(self, file_name)

source code 

Read the context file 'file_name'.

'file_name' -- The name of the context file.

Reads the context file and adds the context properties in the file to 'self'.

__contains__(self, key)
(In operator)

source code 
Returns: True if D has a key k, else False
Overrides: dict.__contains__
(inherited documentation)

get(self, key, default=None)

source code 

d defaults to None.

Returns: D[k] if k in D, else d
Overrides: dict.get
(inherited documentation)

has_key(self, key)

source code 
Returns: True if D has a key k, else False
Overrides: dict.has_key
(inherited documentation)

__getitem__(self, key)
(Indexing operator)

source code 

x[y]

Overrides: dict.__getitem__
(inherited documentation)

items(self)

source code 
Returns: list of D's (key, value) pairs, as 2-tuples
Overrides: dict.items
(inherited documentation)

GetAddedProperties(self)

source code 

Return the properties added to this context by resources.

returns -- A map from strings to values indicating properties that were added to this context by resources.


Class Variable Details [hide private]

DB_PATH_CONTEXT_PROPERTY

The context variable giving the path to the database.

The value of this context variable will be a string giving the path to the database directory. For example, if QMTest is invoked as 'qmtest -D /path/to/db run', the value of this variable would be '/path/to/db'. The value may be an absolute or a relative path.

Value:
'qmtest.dbpath'

ID_CONTEXT_PROPERTY

The context variable giving the name of the running test or resource.

This value of this context variable will be the string giving the name of the of the test or resource that is presently executing.

Value:
'qmtest.id'

TMPDIR_CONTEXT_PROPERTY

A context property whose value is a string giving the path to a temporary directory. This directory will be used only by the 'Runnable' in whose context this property occurs during the execution of that 'Runnable'. No other object will use the same temporary directory at the same time. There is no guarantee that the temporary directory is empty, however; it may contain files left behind by the execution of other 'Runnable' objects.

Value:
'qmtest.tmpdir'

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.temporary.TempDirectoryResource-class.html0000664000076400007640000005572511122067147033355 0ustar stefanstefan qm.test.classes.temporary.TempDirectoryResource
Package qm :: Package test :: Package classes :: Module temporary :: Class TempDirectoryResource
[hide private]
[frames] | no frames]

Class TempDirectoryResource

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
          resource.Resource --+
                              |
                             TempDirectoryResource

Resource class to manage a temporary directory.

An instance of this resource creates a temporary directory during setup, and deletes it during cleanup. The full path to the directory is available to tests via a context property.

Nested Classes [hide private]

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
SetUp(self, context, result)
Set up the resource.
source code
 
CleanUp(self, result)
Clean up the resource.
source code

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [<<class 'qm.fields.TextField'> dir_path_property>...
A list of the arguments to the extension class.
  _argument_dictionary = {'delete_recursively': <<class 'qm.fiel...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.TextField'> dir_path_prop...
A list of all the 'Field's in this class.
  delete_recursively = 1
  dir_path_property = 'temp_dir_path'

Inherited from resource.Resource: kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

SetUp(self, context, result)

source code 

Set up the resource.

'context' -- A 'Context' giving run-time parameters to the resource. The resource may place additional variables into the 'context'; these variables will be visible to tests that depend on the resource.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

Overrides: resource.Resource.SetUp
(inherited documentation)

CleanUp(self, result)

source code 

Clean up the resource.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes may override this method.

Overrides: resource.Resource.CleanUp
(inherited documentation)

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[<<class 'qm.fields.TextField'> dir_path_property>,
 <<class 'qm.fields.IntegerField'> delete_recursively>]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'delete_recursively': <<class 'qm.fields.IntegerField'> delete_recurs\
ively>,
 'dir_path_property': <<class 'qm.fields.TextField'> dir_path_property\
>,
 'resources': <<class 'qm.fields.SetField'> resources>}

_argument_list

A list of all the 'Field's in this class.

This list combines the complete list of 'arguments'. 'Field's appear in the order reached by a pre-order breadth-first traversal of the hierarchy, starting from the most derived class.

Value:
[<<class 'qm.fields.TextField'> dir_path_property>,
 <<class 'qm.fields.SetField'> resources>,
 <<class 'qm.fields.IntegerField'> delete_recursively>]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_base-module.html0000664000076400007640000001130411122067145027600 0ustar stefanstefan qm.test.classes.dejagnu_base
Package qm :: Package test :: Package classes :: Module dejagnu_base
[hide private]
[frames] | no frames]

Module dejagnu_base

source code

Classes [hide private]
  DejaGNUBase
A 'DejaGNUBase' is a base class for tests and resources.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.user-pysrc.html0000664000076400007640000052706011122067155023424 0ustar stefanstefan qm.user
Package qm :: Module user
[hide private]
[frames] | no frames]

Source Code for Module qm.user

  1  ######################################################################## 
  2  # 
  3  # File:   user.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-03-23 
  6  # 
  7  # Contents: 
  8  #   User management facilities. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  """User management facilities. 
 17   
 18  Access to this module is primarily through two global variables. 
 19   
 20    'database' -- The user database.  The database contains objects 
 21    representing users, accessed via a *user ID*.  The user ID is a label 
 22    uniquely identifying the user in the system. 
 23   
 24    The user database also provides a notion of user groups.  Each group 
 25    is identified by a group ID, and contains zero or more user IDs.  A 
 26    user may belong to more than one group.  A group may not contain other 
 27    groups.  
 28   
 29    'authenticator' -- The authenticator object by which the application 
 30    authenticates users who attempt to access it via various channels. 
 31   
 32  Access the database object via this interface: 
 33   
 34    * Use the database object as a Python map from user IDs to 'User' 
 35      objects.  The 'keys' method returns a sequence of user IDs in the 
 36      database.  
 37   
 38    * Call 'GetGroupIds' to return a sequence of group IDs.  Use the 
 39      'GetGroup' method to retrieve a 'Group' object for a given group ID. 
 40   
 41  """ 
 42   
 43  ######################################################################## 
 44  # imports 
 45  ######################################################################## 
 46   
 47  import qm 
 48  import label 
 49  import xmlutil 
 50   
 51  ######################################################################## 
 52  # constants 
 53  ######################################################################## 
 54   
 55  xml_user_database_dtd = "-//Software Carpentry//User Database V0.1//EN" 
 56   
 57  ######################################################################## 
 58  # classes 
 59  ######################################################################## 
 60   
61 -class AuthenticationError(Exception):
62 pass
63 64 65
66 -class XmlDatabaseError(Exception):
67 pass
68 69 70
71 -class AccountDisabledError(AuthenticationError):
72 pass
73 74 75
76 -class User:
77 """A user account record. 78 79 User accounts contain three sets of properties. Each property 80 is a name-value pair. The three sets of properties are: 81 82 informational properties -- General information about the 83 user. This may include the user's real name, contact 84 information, etc. These properties are generally 85 user-visible, and should be modified only at the user's 86 request. 87 88 configuration properties -- Program-specific per-user 89 configuration. This includes user's preferences, such as 90 preferred layout and output options. These properties are 91 typically hidden as implementation details, and are often 92 changed implicitly as part of other operations. 93 94 authentication properties -- Information used to authenticate 95 the user. This may include such things as passwords, PGP 96 keys, and digital certificates. There are no accessors for 97 these properties; they should be used by authenticators only. 98 """ 99 100
101 - def __init__(self, 102 user_id, 103 role="user", 104 enabled=1, 105 information_properties={}, 106 configuration_properties={}, 107 authentication_properties={}):
108 """Create a new user account. 109 110 'user_id' -- The ID for the user. 111 112 'role' -- If "default", this is the default user account (there 113 should be only one). The default account, if provided, is used 114 for otherwise unauthenticated operations. If "admin", this is 115 an administrator account. If "user", this is an ordinary user 116 account. 117 118 'enabled' -- If true, this account is enabled; otherwise, 119 disabled. 120 121 'information_properties' -- A map contianing information 122 properties. 123 124 'configuration_properties' -- A map containing configuration 125 properties. 126 127 'authentication_properties' -- A map containing authentication 128 properties.""" 129 130 self.__id = user_id 131 self.__role = role 132 self.__is_enabled = enabled 133 # Initialize properties. 134 self.__authentication = authentication_properties.copy() 135 self.__configuration = configuration_properties.copy() 136 self.__info = information_properties.copy()
137 138
139 - def GetId(self):
140 """Return the user ID of this user.""" 141 142 return self.__id
143 144
145 - def GetRole(self):
146 """Return the role of this user.""" 147 148 return self.__role
149 150
151 - def IsEnabled(self):
152 """Return true if this account is enabled.""" 153 154 return self.__is_enabled
155 156
157 - def GetConfigurationProperty(self, name, default=None):
158 """Return a configuration property. 159 160 'name' -- The name of the property. 161 162 'default' -- The value to return if this property is not 163 specified for the user account.""" 164 165 return self.__configuration.get(name, default)
166 167
168 - def SetConfigurationProperty(self, name, value):
169 """Set the configuration property 'name' to 'value'.""" 170 171 self.__configuration[name] = value
172 173
174 - def GetInfoProperty(self, name, default=None):
175 """Return an informational property. 176 177 'name' -- The name of the property. 178 179 'default' -- The value to return if this property is not 180 specified for the user account.""" 181 182 return self.__info.get(name, default)
183 184
185 - def SetInfoProperty(self, name, value):
186 """Set the informational property 'name' to 'value'.""" 187 188 self.__info[name] = value
189 190 191
192 -class Group:
193 """A group of users. 194 195 A 'Group' object is treated as an ordinary list of user IDs (except 196 that a user ID may not appear more than once in the list).""" 197
198 - def __init__(self, group_id, user_ids=[]):
199 """Create a new group. 200 201 'group_id' -- The ID of this group. 202 203 'user_ids' -- IDs of users initially in the group.""" 204 205 self.__id = group_id 206 self.__user_ids = list(user_ids)
207 208
209 - def GetId(self):
210 """Return the group_id of this group.""" 211 212 return self.__id
213 214
215 - def __len__(self):
216 return len(self.__user_ids)
217 218
219 - def __getitem__(self, index):
220 return self.__user_ids[index]
221 222
223 - def __setitem__(self, index, user_id):
224 self.__user_ids[index] = user_id 225 # Make sure 'user_id' appears only once. 226 while self.__user_ids.count(user_id) > 1: 227 self.__user_ids.remove(user_id)
228 229
230 - def __delitem__(self, index):
231 del self.__user_ids[index]
232 233
234 - def append(self, user_id):
235 # Don't add a given user more than once. 236 if user_id not in self.__user_ids: 237 self.__user_ids.append(user_id)
238 239
240 - def remove(self, user_id):
241 self.__user_ids.remove(user_id)
242 243 244
245 -class Authenticator:
246 """Base class for authentication classes. 247 248 An 'Authenticator' object is responsible for determining the 249 authenticity of a user. The inputs to an authentication action 250 depend on the mechanism with which the user communicates with the 251 program -- for instance, a web request, command invocation, or email 252 message.""" 253 254
255 - def AuthenticateDefaultUser(self):
256 """Authenticate for the default user, if one is provided. 257 258 returns -- The user ID of the default user.""" 259 260 raise NotImplementedError
261 262
263 - def AuthenticateWebRequest(self, request):
264 """Authenticate a login web request. 265 266 'request' -- A web request containing the user's login 267 information. 268 269 returns -- The user ID of the authenticated user.""" 270 271 raise NotImplementedError
272 273 274
275 -class DefaultDatabase:
276 default_user = User("default_user", "default") 277
278 - def GetDefaultUserId(self):
279 return self.default_user.GetId()
280 281
282 - def keys(self):
283 return [self.GetDefaultUserId()]
284 285
286 - def __getitem__(self, user_id):
287 default_user_id = self.default_user.GetId() 288 if user_id == default_user_id: 289 return self.default_user 290 else: 291 raise KeyError, user_id
292 293
294 - def get(self, user_id, default=None):
295 default_user_id = self.default_user.GetId() 296 if user_id == default_user_id: 297 return self.default_user 298 else: 299 return None
300 301
302 - def GetGroupIds(self):
303 return []
304 305
306 - def GetGroup(self, group_id):
307 raise KeyError, "no such group"
308 309 310
311 -class DefaultAuthenticator(Authenticator):
312 """Authenticator for only a single user, "default_user".""" 313
314 - def AuthenticateDefaultUser(self):
316 317
318 - def AuthenticateWebRequest(self, request):
320 321 322
323 -class XmlDatabase:
324 """An XML user database. 325 326 An object of this class behaves as a read-only map from user IDs to 327 'User' objects.""" 328
329 - def __init__(self, database_path):
330 """Read in the XML user database.""" 331 332 document = xmlutil.load_xml_file(database_path) 333 self.__path = database_path 334 335 node = document.documentElement 336 assert node.tagName == "users" 337 338 self.__users = {} 339 self.__groups = {} 340 self.__default_user_id = None 341 342 # Load users. 343 for user_node in node.getElementsByTagName("user"): 344 user = get_user_from_dom(user_node) 345 # Store the account. 346 self.__users[user.GetId()] = user 347 # Make note if this is the default user. 348 if user.GetRole() == "default": 349 if self.__default_user_id is not None: 350 # More than one default user was specified. 351 raise XmlDatabaseError, "multiple default users" 352 self.__default_user_id = user.GetId() 353 354 # Load groups. 355 for group_node in node.getElementsByTagName("group"): 356 group = get_group_from_dom(group_node) 357 # Make sure all the user IDs listed for this group are IDs 358 # we know. 359 for user_id in group: 360 if not self.__users.has_key(user_id): 361 raise XmlDatabaseError, \ 362 'user "%s" in group "%s" is unknown' \ 363 % (user_id, group.GetId()) 364 # Store the group. 365 self.__groups[group.GetId()] = group
366 367 368
369 - def GetDefaultUserId(self):
370 """Return the ID of the default user, or 'None'.""" 371 372 return self.__default_user_id
373 374
375 - def GetGroupIds(self):
376 """Return the IDs of user groups.""" 377 378 return self.__groups.keys()
379 380
381 - def GetGroup(self, group_id):
382 """Return the group with ID 'group_id'.""" 383 384 return self.__groups[group_id]
385 386
387 - def Write(self):
388 """Write out the user database.""" 389 390 # Create a DOM document for the database. 391 document = xmlutil.create_dom_document( 392 public_id = "User", 393 document_element_tag="users" 394 ) 395 document_element = document.documentElement 396 # Create elements for users in the database. 397 for user in self.__users.values(): 398 user_element = create_dom_for_user(document, user) 399 document_element.appendChild(user_element) 400 # Create elements for user groups. 401 for group in self.__groups.values(): 402 group_element = create_dom_for_group(document, group) 403 document_element.appendChild(group_element) 404 # Write out the database. 405 document.writexml(open(self.__path, "w"))
406 407 408 # Methods for emulating a map object. 409
410 - def __getitem__(self, user_id):
411 return self.__users[user_id]
412 413
414 - def get(self, user_id, default=None):
415 return self.__get(user_id, default)
416 417
418 - def keys(self):
419 return self.__users.keys()
420 421 422
423 -class XmlDatabaseAuthenticator(Authenticator):
424 """An authenticator based on contents of the XML user database.""" 425
426 - def __init__(self, database):
427 """Create a new authenticator. 428 429 Authentication is performed based on information stored in 430 'XmlDatabase' instance 'database'.""" 431 432 assert isinstance(database, XmlDatabase) 433 self.__database = database
434 435
436 - def AuthenticateDefaultUser(self):
437 # Try to perform a password authentication for the default user 438 # with an empty password. 439 default_user_id = self.__database.GetDefaultUserId() 440 return self.AuthenticatePassword(default_user_id, "")
441 442
443 - def AuthenticateWebRequest(self, request):
444 # Extract the user name and password from the web request. 445 user_name = request["_login_user_name"] 446 password = request["_login_password"] 447 return self.AuthenticatePassword(user_name, password)
448 449
450 - def AuthenticatePassword(self, user_name, password):
451 try: 452 # Look up the user ID. 453 user = database[user_name] 454 expected_password = user._User__authentication.get("password", 455 None) 456 except KeyError: 457 # No user was found with this user ID. 458 expected_password = None 459 if expected_password is None \ 460 or expected_password != password: 461 # No password specified for this user, or the provided 462 # password doesn't match. 463 raise AuthenticationError, "invalid user name/password" 464 # Is the account enabled? 465 if not user.IsEnabled(): 466 # No. Prevent authentication. 467 raise AccountDisabledError, user_name 468 return user_name
469 470 471 472 ######################################################################## 473 # functions 474 ######################################################################## 475
476 -def load_xml_database(path):
477 """Load users from XML database at 'path' and set up authenticator.""" 478 479 global database 480 global authenticator 481 482 # Use a finally block to make sure either both are set, or neither. 483 try: 484 xml_database = XmlDatabase(path) 485 xml_authenticator = XmlDatabaseAuthenticator(xml_database) 486 except: 487 raise 488 else: 489 database = xml_database 490 authenticator = xml_authenticator
491 492
493 -def get_user_from_dom(user_node):
494 """Construct a 'User' object from a user DOM element. 495 496 'user_node' -- A "user" DOM element. 497 498 returns -- A 'User' object.""" 499 500 assert user_node.tagName == "user" 501 502 # The user ID is stored in the ID attribute of the user element. 503 user_id = user_node.getAttribute("id") 504 # Also the role. 505 role = user_node.getAttribute("role") 506 # Determine whether the account is disabled. 507 enabled = user_node.getAttribute("disabled") == "no" 508 # Read properties. 509 info_properties = _get_dom_properties(user_node, "info") 510 auth_properties = _get_dom_properties(user_node, "authentication") 511 conf_properties = _get_dom_properties(user_node, "configuration") 512 # Create the user object. 513 return User(user_id, role, enabled, 514 info_properties, conf_properties, auth_properties)
515 516
517 -def _get_dom_properties(node, tag):
518 """Return a dictionary of properties from a user DOM element node. 519 520 'node' -- A "user" DOM element. 521 522 'tag' -- The tag of the child element in which to look for 523 properties. 524 525 returns -- A map from property names to values.""" 526 527 # Find all child elements of 'node' with 'tag'. 528 elements = node.getElementsByTagName(tag) 529 if len(elements) == 0: 530 # The child may be omitted; that's OK. 531 return {} 532 # There element, if provided, should be unique. 533 assert len(elements) == 1 534 element = elements[0] 535 # Start a map of properties. 536 properties = {} 537 # Loop over property sub-elements. 538 for property_node in element.getElementsByTagName("property"): 539 # The property name is stored in the name attribute. 540 name = property_node.getAttribute("name") 541 # The property value is stored as a child text node. 542 value = xmlutil.get_dom_text(property_node) 543 properties[name] = value 544 return properties
545 546
547 -def create_dom_for_user(document, user):
548 """Create a DOM element node for 'user'. 549 550 'document' -- The DOM document object in which to create the 551 element. 552 553 'user' -- A 'User' instance. 554 555 returns -- A DOM element node.""" 556 557 # Create the user element. 558 element = document.createElement("user") 559 element.setAttribute("id", user.GetId()) 560 element.setAttribute("role", user.GetRole()) 561 if user.IsEnabled(): 562 disabled_attribute = "no" 563 else: 564 disabled_attribute = "yes" 565 element.setAttribute("disabled", disabled_attribute) 566 # Add informational properties. 567 info_properties_element = document.createElement("info") 568 _create_dom_properties(info_properties_element, user._User__info) 569 element.appendChild(info_properties_element) 570 # Add authentication properties. 571 auth_properties_element = document.createElement("authentication") 572 _create_dom_properties(auth_properties_element, user._User__authentication) 573 element.appendChild(auth_properties_element) 574 # Add configuration properties. 575 conf_properties_element = document.createElement("configuration") 576 _create_dom_properties(conf_properties_element, user._User__configuration) 577 element.appendChild(conf_properties_element) 578 # All done. 579 return element
580 581
582 -def _create_dom_properties(element, properties):
583 """Add user properties to a DOM element. 584 585 'element' -- A DOM element node to which properties are to be added 586 as children. 587 588 'properties' -- A map from property names to values.""" 589 590 document = element.ownerDocument 591 for name, value in properties.items(): 592 prop_element = xmlutil.create_dom_text_element( 593 document, "property", str(value)) 594 prop_element.setAttribute("name", name) 595 element.appendChild(prop_element)
596 597
598 -def get_group_from_dom(group_node):
599 """Construct a 'Group' object from a DOM element. 600 601 'group_node' -- A DOM "group" element node. 602 603 returns -- A 'Group' object.""" 604 605 assert group_node.tagName == "group" 606 607 group_id = group_node.getAttribute("id") 608 user_ids = xmlutil.get_child_texts(group_node, "user-id") 609 # Make the group. 610 return Group(group_id, user_ids)
611 612
613 -def create_dom_for_group(document, group):
614 """Create a DOM element node for 'group'. 615 616 'document' -- The DOM document object in which to create the 617 element. 618 619 'group' -- A 'Group' instance. 620 621 returns -- A DOM element node.""" 622 623 element = document.createElement("group") 624 element.setAttribute("id", group.GetId()) 625 for user_id in group: 626 user_id_element = xmlutil.create_dom_text_element( 627 document, "user-id", user_id) 628 element.appendChild(user_id_element) 629 return element
630 631 632 ######################################################################## 633 # variables 634 ######################################################################## 635 636 database = DefaultDatabase() 637 authenticator = DefaultAuthenticator() 638 639 ######################################################################## 640 # Local Variables: 641 # mode: python 642 # indent-tabs-mode: nil 643 # fill-column: 72 644 # End: 645

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.setup-module.html0000664000076400007640000000230111122067144024476 0ustar stefanstefan setup

Module setup


Functions

find_packages_r

Variables

packages

[hide private] ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate.InstanceDic0000664000076400007640000002224011122067146033242 0ustar stefanstefan qm.external.DocumentTemplate.pDocumentTemplate.InstanceDict
Package qm :: Package external :: Package DocumentTemplate :: Module pDocumentTemplate :: Class InstanceDict
[hide private]
[frames] | no frames]

Class InstanceDict

source code

Instance Methods [hide private]
 
__init__(self, o, namespace, validate=None) source code
 
has_key(self, key) source code
 
keys(self) source code
 
__repr__(self) source code
 
__getitem__(self, key) source code
Class Variables [hide private]
  validate = None
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_With-module.html0000664000076400007640000001523111122067145031156 0ustar stefanstefan qm.external.DocumentTemplate.DT_With
Package qm :: Package external :: Package DocumentTemplate :: Module DT_With
[hide private]
[frames] | no frames]

Module DT_With

source code

Nested namespace access

The 'with' tag is used to introduce nested namespaces.

The text enclosed in the with tag is rendered using information from the given variable or expression.

For example, if the variable 'person' is bound to an object that has attributes 'name' and 'age', then a 'with' tag like the following can be used to access these attributes:

 <!--#with person-->
   <!--#var name-->,
   <!--#var age-->
 <!--#/with-->

Eather a 'name' or an 'expr' attribute may be used to specify data. A 'mapping' attribute may be used to indicate that the given data should be treated as mapping object, rather than as an object with named attributes.


Version: 1069

Classes [hide private]
  With
Variables [hide private]
  __rcs_id__ = '$Id: DT_With.py 1069 2008-11-13 21:55:43Z stefan $'
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.attachment-module.html0000664000076400007640000003203611122067145024714 0ustar stefanstefan qm.attachment
Package qm :: Module attachment
[hide private]
[frames] | no frames]

Module attachment

source code

Code for handling arbitrary file attachments.

'Attachment' is a base class for classes that represent arbitrary
attachments.  Each 'Attachment' object has these four attributes:

  'mime_type' -- The MIME type of the attachment contents.  This
  information enables user interfaces to handle attachment data in a
  sensible fasion.

  'description' -- The user's description of the attachment contents.

  'file_name' -- A file name associated with the description.  This is
  usually the name of the file from which the attachment was originally
  uploaded or inserted.

  'location' -- A string containing the external location of the
  attachment data.  The semantics of this string are defined by
  implementations of 'AttachmentStore', which use it to locate the
  attachment's data.

A special 'TemporaryAttachmentStore', with a different interface, is
used to store attachment data temporarily, at most for the life of the
program.  The 'temporary_store' global instance should be used.

Classes [hide private]
  Attachment
An arbitrary file attachment.
  AttachmentStore
Interface for classes which store attachment data.
  FileAttachmentStore
An attachment store based on the file system.
  TemporaryAttachmentStore
Temporary storage for attachment data.
Functions [hide private]
 
make_temporary_location()
Return a unique location for temporary attachment data.
source code
 
make_dom_node(attachment, document)
Create a DOM element node for this attachment.
source code
 
from_dom_node(node, store)
Construct an attachment object from a DOM element node.
source code
Variables [hide private]
  _temporary_location_prefix = '_temporary'
Function Details [hide private]

make_dom_node(attachment, document)

source code 

Create a DOM element node for this attachment.

'document' -- A DOM document node in which to create the element.

returns -- A DOM element node.

from_dom_node(node, store)

source code 

Construct an attachment object from a DOM element node.

'node' -- A DOM attachment element node.

'store' -- The associated attachment store.

returns -- An attachment instance. The type is determined by 'attachment_class'.

If the attachment object requires additional context information to interpret the location (if it's specified in the attachment element), the caller must provide it directly to the object.


././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DocumentTemplate-module.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DocumentTemplate-module.h0000664000076400007640000000217211122067144033173 0ustar stefanstefan DocumentTemplate

Module DocumentTemplate


Variables

ParseError

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web-pysrc.html0000664000076400007640000001542611122067161024174 0ustar stefanstefan qm.test.web
Package qm :: Package test :: Package web
[hide private]
[frames] | no frames]

Source Code for Package qm.test.web

 1  ######################################################################## 
 2  # 
 3  # File:   __init__.py 
 4  # Author: Alex Samuel 
 5  # Date:   2001-04-09 
 6  # 
 7  # Contents: 
 8  #   Initialization for module qm.test.web. 
 9  # 
10  # Copyright (c) 2001 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Local Variables: 
18  # mode: python 
19  # indent-tabs-mode: nil 
20  # fill-column: 72 
21  # End: 
22   

././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.pDocumentTemplate.MultiMappin0000664000076400007640000002007211122067146033316 0ustar stefanstefan qm.external.DocumentTemplate.pDocumentTemplate.MultiMapping
Package qm :: Package external :: Package DocumentTemplate :: Module pDocumentTemplate :: Class MultiMapping
[hide private]
[frames] | no frames]

Class MultiMapping

source code

Instance Methods [hide private]
 
__init__(self) source code
 
__getitem__(self, key) source code
 
push(self, d) source code
 
pop(self, n=1) source code
 
keys(self) source code
qmtest-2.4.1/share/doc/qmtest/html/manual/math-module.html0000664000076400007640000006002311122067145023076 0ustar stefanstefan math
Module math
[hide private]
[frames] | no frames]

Module math

This module is always available. It provides access to the mathematical functions defined by the C standard.

Functions [hide private]
 
acos(x)
Return the arc cosine (measured in radians) of x.
 
asin(x)
Return the arc sine (measured in radians) of x.
 
atan(x)
Return the arc tangent (measured in radians) of x.
 
atan2(y, x)
Return the arc tangent (measured in radians) of y/x.
 
ceil(x)
Return the ceiling of x as a float.
 
cos(x)
Return the cosine of x (measured in radians).
 
cosh(x)
Return the hyperbolic cosine of x.
converts angle x from radians to degrees
degrees(x)
 
exp(x)
Return e raised to the power of x.
 
fabs(x)
Return the absolute value of the float x.
 
floor(x)
Return the floor of x as a float.
 
fmod(x, y)
Return fmod(x, y), according to platform C.
 
frexp(x)
Return the mantissa and exponent of x, as pair (m, e).
 
hypot(x, y)
Return the Euclidean distance, sqrt(x*x + y*y).
x * (2**i)
ldexp(x, i)
the logarithm of x to the given base
log(x, base=...)
If the base not specified, returns the natural logarithm (base e) of x.
the base 10 logarithm of x.
log10(x)
 
modf(x)
Return the fractional and integer parts of x.
 
pow(x, y)
Return x**y (x to the power of y).
converts angle x from degrees to radians
radians(x)
 
sin(x)
Return the sine of x (measured in radians).
 
sinh(x)
Return the hyperbolic sine of x.
 
sqrt(x)
Return the square root of x.
 
tan(x)
Return the tangent of x (measured in radians).
 
tanh(x)
Return the hyperbolic tangent of x.
Variables [hide private]
  e = 2.71828182846
  pi = 3.14159265359
Function Details [hide private]

atan2(y, x)

 

Return the arc tangent (measured in radians) of y/x. Unlike atan(y/x), the signs of both x and y are considered.

ceil(x)

 

Return the ceiling of x as a float. This is the smallest integral value >= x.

floor(x)

 

Return the floor of x as a float. This is the largest integral value <= x.

fmod(x, y)

 

Return fmod(x, y), according to platform C. x % y may differ.

frexp(x)

 

Return the mantissa and exponent of x, as pair (m, e). m is a float and e is an int, such that x = m * 2.**e. If x is 0, m and e are both 0. Else 0.5 <= abs(m) < 1.0.

modf(x)

 

Return the fractional and integer parts of x. Both results carry the sign of x. The integer part is returned as a real.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.config-pysrc.html0000664000076400007640000001255211122067152023703 0ustar stefanstefan qm.config
Package qm :: Module config
[hide private]
[frames] | no frames]

Source Code for Module qm.config

1  version='snapshot' 
2  data_dir='share/qmtest' 
3  doc_dir='share/doc/qmtest' 
4  # The following variables are set / adjusted during 
5  # the build / install process. 
6  extension_path='qm/test/classes' 
7   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.base.CouldNotLoadExtensionError-class.html0000664000076400007640000002235011122067146031530 0ustar stefanstefan qm.test.base.CouldNotLoadExtensionError
Package qm :: Package test :: Module base :: Class CouldNotLoadExtensionError
[hide private]
[frames] | no frames]

Class CouldNotLoadExtensionError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  CouldNotLoadExtensionError

An exception indicating that an extension class could not be loaded.

Instance Methods [hide private]
 
__init__(self, class_name, exc_info)
Construct a new 'CouldNotLoadExtensionError'.
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, class_name, exc_info)
(Constructor)

source code 

Construct a new 'CouldNotLoadExtensionError'.

'class_name' -- The name of the class.

'exc_info' -- An exception tuple, as returned by 'sys.exc_info'.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.PrivilegedPortError-class.html0000664000076400007640000001537111122067151027131 0ustar stefanstefan qm.web.PrivilegedPortError
Package qm :: Module web :: Class PrivilegedPortError
[hide private]
[frames] | no frames]

Class PrivilegedPortError

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  PrivilegedPortError

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.run_database-module.html0000664000076400007640000001110411122067145026163 0ustar stefanstefan qm.test.run_database
Package qm :: Package test :: Module run_database
[hide private]
[frames] | no frames]

Module run_database

source code

Classes [hide private]
  RunDatabase
A 'RunDatabase' stores 'TestRun's.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.WebRequest-class.html0000664000076400007640000006003011122067151025236 0ustar stefanstefan qm.web.WebRequest
Package qm :: Module web :: Class WebRequest
[hide private]
[frames] | no frames]

Class WebRequest

source code

An object representing a request from the web server.

A 'WebRequest' object behaves as a dictionary of key, value pairs representing query arguments, for instance query fields in a POST, or arguments encoded in a URL query string. It has some other methods as well.

Instance Methods [hide private]
 
__init__(self, script_url, base=None, keep_fields=False, **fields)
Create a new request object.
source code
 
__str__(self) source code
 
GetUrl(self)
Return the URL of the script that processes this request.
source code
 
GetScriptName(self)
Return the name of the script that processes this request.
source code
 
SetSessionId(self, session_id)
Set the session ID for this request to 'session_id'.
source code
 
GetSessionId(self)
Return the session ID for this request.
source code
 
GetSession(self)
Return the session for this request.
source code
 
AsUrl(self, last_argument=None)
Return the URL representation of this request.
source code
 
AsForm(self, method='get', name=None)
Return an opening form tag for this request.
source code
 
__getitem__(self, key) source code
 
__setitem__(self, key, value) source code
 
__delitem__(self, key) source code
 
get(self, key, default=None) source code
 
keys(self) source code
 
has_key(self, key) source code
 
items(self) source code
 
copy(self, url=None, **fields)
Return a duplicate of this request.
source code
Method Details [hide private]

__init__(self, script_url, base=None, keep_fields=False, **fields)
(Constructor)

source code 

Create a new request object.

'script_url' -- The URL of the script that processes this query.

'base' -- A request object from which the session ID will be duplicated, or 'None'.

'fields' -- The query arguments.

GetScriptName(self)

source code 

Return the name of the script that processes this request.

The script name is the final element of the full URL path.

GetSessionId(self)

source code 

Return the session ID for this request.

returns -- A session ID, or 'None'.

GetSession(self)

source code 

Return the session for this request.

raises -- 'NoSessionError' if no session ID is specified in the request.

raises -- 'InvalidSessionError' if the session ID specified in the request is invalid.

AsUrl(self, last_argument=None)

source code 

Return the URL representation of this request.

'fields_at_end' -- If not 'None', the name of the URL query arguments that should be placed last in the list of arugmnets (other than this, the order of query arguments is not defined).

AsForm(self, method='get', name=None)

source code 

Return an opening form tag for this request.

'method' -- The HTML method to use for the form, either "get" or "post".

'name' -- A name for the form, or 'None'.

returns -- An opening form tag for the request, plus hidden input elements for arguments to the request.

The caller must add additional inputs, the submit input, and close the form tag.

copy(self, url=None, **fields)

source code 

Return a duplicate of this request.

'url' -- The URL for the request copy. If 'None', use the URL of the source.

'**fields' -- Additional fields to set in the copy.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes-pysrc.html0000664000076400007640000001543411122067152025053 0ustar stefanstefan qm.test.classes
Package qm :: Package test :: Package classes
[hide private]
[frames] | no frames]

Source Code for Package qm.test.classes

 1  ######################################################################## 
 2  # 
 3  # File:   __init__.py 
 4  # Author: Mark Mitchell 
 5  # Date:   2003-11-23 
 6  # 
 7  # Contents: 
 8  #   Module initialization. 
 9  # 
10  # Copyright (c) 2001 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Local Variables: 
18  # mode: python 
19  # indent-tabs-mode: nil 
20  # fill-column: 72 
21  # End: 
22   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_With-pysrc.html0000664000076400007640000014042111122067156031033 0ustar stefanstefan qm.external.DocumentTemplate.DT_With
Package qm :: Package external :: Package DocumentTemplate :: Module DT_With
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_With

 1  ############################################################################## 
 2  # 
 3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
 4  # 
 5  # This software is subject to the provisions of the Zope Public License, 
 6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
 7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
 8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
 9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
10  # FOR A PARTICULAR PURPOSE 
11  # 
12  ############################################################################## 
13  '''Nested namespace access 
14   
15     The 'with' tag is used to introduce nested namespaces. 
16   
17     The text enclosed in the with tag is rendered using information 
18     from the given variable or expression. 
19   
20     For example, if the variable 'person' is bound to an object that 
21     has attributes 'name' and 'age', then a 'with' tag like the 
22     following can be used to access these attributes:: 
23   
24       <!--#with person--> 
25         <!--#var name-->, 
26         <!--#var age--> 
27       <!--#/with--> 
28   
29     Eather a 'name' or an 'expr' attribute may be used to specify data. 
30     A 'mapping' attribute may be used to indicate that the given data 
31     should be treated as mapping object, rather than as an object with 
32     named attributes. 
33   
34  ''' 
35   
36  __rcs_id__='$Id: DT_With.py 1069 2008-11-13 21:55:43Z stefan $' 
37  __version__='$Revision: 1069 $'[11:-2] 
38   
39  from DT_Util import parse_params, name_param, InstanceDict, render_blocks, str 
40  from DT_Util import TemplateDict 
41 -class With:
42 blockContinuations=() 43 name='with' 44 mapping=None 45 only=0 46
47 - def __init__(self, blocks):
48 tname, args, section = blocks[0] 49 args=parse_params(args, name='', expr='', mapping=1, only=1) 50 name,expr=name_param(args,'with',1) 51 if expr is None: expr=name 52 else: expr=expr.eval 53 self.__name__, self.expr = name, expr 54 self.section=section.blocks 55 if args.has_key('mapping') and args['mapping']: self.mapping=1 56 if args.has_key('only') and args['only']: self.only=1
57
58 - def render(self, md):
59 expr=self.expr 60 if type(expr) is type(''): v=md[expr] 61 else: v=expr(md) 62 63 if not self.mapping: 64 if type(v) is type(()) and len(v)==1: v=v[0] 65 v=InstanceDict(v,md) 66 67 if self.only: 68 _md=md 69 md=TemplateDict() 70 if hasattr(_md, 'validate'): 71 md.validate=_md.validate 72 73 md._push(v) 74 try: return render_blocks(self.section, md) 75 finally: md._pop(1)
76 77 __call__=render
78

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.file_label-module.html0000664000076400007640000000212611122067144030033 0ustar stefanstefan file_label

Module file_label


Classes

FileLabel

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/random-module.html0000664000076400007640000011533311122067145023432 0ustar stefanstefan random
Module random
[hide private]
[frames] | no frames]

Module random

source code

Random variable generators.

    integers
    --------
           uniform within range

    sequences
    ---------
           pick random element
           pick random sample
           generate random permutation

    distributions on the real line:
    ------------------------------
           uniform
           normal (Gaussian)
           lognormal
           negative exponential
           gamma
           beta
           pareto
           Weibull

    distributions on the circle (angles 0 to 2pi)
    ---------------------------------------------
           circular uniform
           von Mises

General notes on the underlying Mersenne Twister core generator:

* The period is 2**19937-1.
* It is one of the most extensively tested generators in existence.
* Without a direct way to compute N steps forward, the semantics of
  jumpahead(n) are weakened to simply jump to another distant state and rely
  on the large period to avoid overlapping sequences.
* The random() method is implemented in C, executes in a single Python step,
  and is, therefore, threadsafe.

Classes [hide private]
  Random
Random number generator base class used by bound module functions.
  SystemRandom
Alternate random number generator using sources provided by the operating system (such as /dev/urandom on Unix or CryptGenRandom on Windows).
  WichmannHill
Functions [hide private]
 
_test(N=2000) source code
 
_test_generator(n, func, args) source code
 
betavariate(alpha, beta)
Beta distribution.
source code
 
choice(seq)
Choose a random element from a non-empty sequence.
source code
 
expovariate(lambd)
Exponential distribution.
source code
 
gammavariate(alpha, beta)
Gamma distribution.
source code
 
gauss(mu, sigma)
Gaussian distribution.
source code
x
getrandbits(k)
Generates a long int with k random bits.
source code
 
getstate()
Return internal state; can be passed to setstate() later.
source code
None
jumpahead(int)
Create new state from existing state and integer.
source code
 
lognormvariate(mu, sigma)
Log normal distribution.
source code
 
normalvariate(mu, sigma)
Normal distribution.
source code
 
paretovariate(alpha)
Pareto distribution.
source code
 
randint(a, b)
Return random integer in range [a, b], including both end points.
source code
x in the interval [0, 1).
random() source code
 
randrange(start, stop=None, step=1, int=<type 'int'>, default=None, maxwidth=9007199254740992)
Choose a random item from range(start, stop[, step]).
source code
 
sample(population, k)
Chooses k unique random elements from a population sequence.
source code
 
seed(a=None)
Initialize internal state from hashable object.
source code
 
setstate(state)
Restore internal state from object returned by getstate().
source code
 
shuffle(x, random=None, int=<type 'int'>)
x, random=random.random -> shuffle list x in place; return None.
source code
 
uniform(a, b)
Get a random number in the range [a, b).
source code
 
vonmisesvariate(mu, kappa)
Circular data distribution.
source code
 
weibullvariate(alpha, beta)
Weibull distribution.
source code
Variables [hide private]
  BPF = 53
  LOG4 = 1.38629436112
  NV_MAGICCONST = 1.71552776992
  RECIP_BPF = 1.11022302463e-16
  SG_MAGICCONST = 2.50407739678
  TWOPI = 6.28318530718
  _e = 2.71828182846
  _inst = <random.Random object at 0x2a1bb70>
  _pi = 3.14159265359
Function Details [hide private]

betavariate(alpha, beta)

source code 

Beta distribution.

Conditions on the parameters are alpha > 0 and beta > 0. Returned values range between 0 and 1.

expovariate(lambd)

source code 

Exponential distribution.

lambd is 1.0 divided by the desired mean. (The parameter would be called "lambda", but that is a reserved word in Python.) Returned values range from 0 to positive infinity.

gammavariate(alpha, beta)

source code 

Gamma distribution. Not the gamma function!

Conditions on the parameters are alpha > 0 and beta > 0.

gauss(mu, sigma)

source code 

Gaussian distribution.

mu is the mean, and sigma is the standard deviation. This is slightly faster than the normalvariate() function.

Not thread-safe without a lock around calls.

lognormvariate(mu, sigma)

source code 

Log normal distribution.

If you take the natural logarithm of this distribution, you'll get a normal distribution with mean mu and standard deviation sigma. mu can have any value, and sigma must be greater than zero.

normalvariate(mu, sigma)

source code 

Normal distribution.

mu is the mean, and sigma is the standard deviation.

paretovariate(alpha)

source code 

Pareto distribution. alpha is the shape parameter.

randrange(start, stop=None, step=1, int=<type 'int'>, default=None, maxwidth=9007199254740992)

source code 

Choose a random item from range(start, stop[, step]).

This fixes the problem with randint() which includes the endpoint; in Python this is usually not what you want. Do not supply the 'int', 'default', and 'maxwidth' arguments.

sample(population, k)

source code 

Chooses k unique random elements from a population sequence.

Returns a new list containing elements from the population while leaving the original population unchanged. The resulting list is in selection order so that all sub-slices will also be valid random samples. This allows raffle winners (the sample) to be partitioned into grand prize and second place winners (the subslices).

Members of the population need not be hashable or unique. If the population contains repeats, then each occurrence is a possible selection in the sample.

To choose a sample in a range of integers, use xrange as an argument. This is especially fast and space efficient for sampling from a large population: sample(xrange(10000000), 60)

seed(a=None)

source code 

Initialize internal state from hashable object.

None or no argument seeds from current time or from an operating system specific randomness source if available.

If a is not None or an int or long, hash(a) is used instead.

shuffle(x, random=None, int=<type 'int'>)

source code 

x, random=random.random -> shuffle list x in place; return None.

Optional arg random is a 0-argument function returning a random float in [0.0, 1.0); by default, the standard random.random.

vonmisesvariate(mu, kappa)

source code 

Circular data distribution.

mu is the mean angle, expressed in radians between 0 and 2*pi, and kappa is the concentration parameter, which must be greater than or equal to zero. If kappa is equal to zero, this distribution reduces to a uniform random angle over the range 0 to 2*pi.

weibullvariate(alpha, beta)

source code 

Weibull distribution.

alpha is the scale parameter and beta is the shape parameter.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.pickle_result_stream-pysrc.html0000664000076400007640000036720411122067162031300 0ustar stefanstefan qm.test.classes.pickle_result_stream
Package qm :: Package test :: Package classes :: Module pickle_result_stream
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.pickle_result_stream

  1  ######################################################################## 
  2  # 
  3  # File:   pickle_result_stream.py 
  4  # Author: Mark Mitchell 
  5  # Date:   11/25/2002 
  6  # 
  7  # Contents: 
  8  #   PickleResultStream, PickleResultReader 
  9  # 
 10  # Copyright (c) 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  ######################################################################## 
 15  # Imports 
 16  ######################################################################## 
 17   
 18  import types 
 19  import cPickle 
 20  import struct 
 21  import qm.fields 
 22  from   qm.test.file_result_stream import FileResultStream 
 23  from   qm.test.file_result_reader import FileResultReader 
 24   
 25  ######################################################################## 
 26  # Constants 
 27  ######################################################################## 
 28   
 29  # A subtlety is that because of how extension classes are loaded, we 
 30  # can't use the standard trick of using a nonce class for our sentinel, 
 31  # because the unpickler won't be able to find the class definition.  But 
 32  # 'None' has no other meaning in our format, so works fine. 
 33  _annotation_sentinel = None 
 34  """The sentinel value that marks the beginning of an annotation.""" 
 35   
 36  # Network byte order, 4 byte unsigned int 
 37  _int_format = "!I" 
 38  _int_size = struct.calcsize(_int_format) 
 39   
 40  ######################################################################## 
 41  # Classes 
 42  ######################################################################## 
 43   
44 -class PickleResultStream(FileResultStream):
45 """A 'PickleResultStream' writes out results as Python pickles. 46 47 See also 'PickleResultReader', which does the reverse.""" 48 49 _max_pinned_results = 1000 50 """A limit on how many `Result's to pin in memory at once. 51 52 Pickling an object normally pins it in memory; this is necessary 53 to ensure correct behaviour when pickling multiple references to 54 the same object. We know that `Result's can't refer to each 55 other, so this pinning is useless overhead; however, clearing the 56 cache at every call to `WriteResult' slows down both pickling and 57 unpickling by about a factor of two. As a solution, any given 58 `PickleResultStream', will clear its cache after 59 `_max_pinned_results' calls to WriteResult. This cache-clearing 60 technique causes a very minor slowdown on small result streams, 61 and a substantial speedup on large result streams.""" 62 63 _format_version = 1 64 """The version number of the format we write. 65 66 This is bumped every time the format is changed, to make sure that 67 we can retain backwards compatibility. 68 69 "Version 0" contains no version number, and is simply a bunch 70 of 'Result's pickled one after another. 71 72 "Version 1", and all later versions, contain a pickled version 73 number as the first thing in the file. In version 1, this is 74 followed by a 4-byte unsigned integer in network byte order giving 75 the address of the first annotation, followed by the file proper. 76 The file proper is composed of a bunch of pickled 'Result's, 77 followed by a pickled sentinel value (None), followed by a 4-byte 78 unsigned integer in network-byte order, followed by the beginning of 79 a new pickle whose first item is a annotation tuple, and following 80 items are more 'Result's, and then another sentinel value, and so 81 on. An annotation tuple is a tuple of n items, the first of which 82 is a string tagging the type of annotation, and the rest of which 83 have an interpretation that depends on the tag found. The only tag 84 currently defined is "annotation", which is followed by two string 85 elements giving respectively the key and the value. The 4-byte 86 integers always point to the file address of the next such integer, 87 except for the last, which has a value of 0; they are used to 88 quickly find all annotations.""" 89 90 arguments = [ 91 qm.fields.IntegerField( 92 name = "protocol_version", 93 description = """The pickle protocol version to use. 94 95 There are multiple versions of the pickle protocol; in 96 general, higher numbers correspond to faster operation and 97 more compact files, but may produce files that cannot be 98 understood by older versions of Python. 99 100 As of 2003-06-20, the defined protocol versions are: 101 0: Traditional ASCII-only format. 102 1: Traditional binary format. 103 2: New binary format. 104 -1: Equivalent to the highest version supported by your 105 Python release. 106 Pickle versions 0 and 1 can be understood by any version 107 of Python; version 2 pickles can only be created or 108 understood by Python 2.3 and newer. (See PEP 307 for 109 details.) 110 111 Currently the default version is 1. 112 113 """, 114 default_value = 1, 115 ), 116 ] 117 118 _is_binary_file = 1 119
120 - def __init__(self, arguments = None, **args):
121 122 # Initialize the base class. 123 super(PickleResultStream, self).__init__(arguments, **args) 124 # Create initial pickler. 125 self._ResetPickler() 126 # We haven't processed any `Result's yet. 127 self.__processed = 0 128 129 # Write out version number. 130 self.__pickler.dump(self._format_version) 131 # We have no previous annotations. 132 self.__last_annotation = None 133 # Write out annotation header. 134 self._WriteAnnotationPtr()
135 136
137 - def _ResetPickler(self):
138 139 self.__pickler = cPickle.Pickler(self.file, self.protocol_version)
140 141
142 - def _WriteAnnotationPtr(self):
143 144 new_annotation = self.file.tell() 145 if self.__last_annotation is not None: 146 self.file.seek(self.__last_annotation) 147 self.file.write(struct.pack(_int_format, new_annotation)) 148 self.file.seek(new_annotation) 149 self.file.write(struct.pack(_int_format, 0)) 150 self.__last_annotation = new_annotation 151 self._ResetPickler()
152 153
154 - def WriteAnnotation(self, key, value):
155 156 assert isinstance(key, types.StringTypes) 157 assert isinstance(value, types.StringTypes) 158 self.__pickler.dump(_annotation_sentinel) 159 self._WriteAnnotationPtr() 160 self.__pickler.dump(("annotation", key, value))
161 162
163 - def WriteResult(self, result):
164 165 self.__pickler.dump(result) 166 self.__processed += 1 167 # If enough results have been pickeled, clear the pickling 168 # cache. 169 if not self.__processed % self._max_pinned_results: 170 self.__pickler.clear_memo()
171 172 173
174 -class PickleResultReader(FileResultReader):
175 """A 'PickleResultReader' reads in results from pickle files. 176 177 See also 'PickleResultStream', which does the reverse.""" 178
179 - def __init__(self, arguments = None, **args):
180 181 super(PickleResultReader, self).__init__(arguments, **args) 182 self._ResetUnpickler() 183 184 self._annotations = {} 185 186 # Check for a version number 187 try: 188 version = self.__unpickler.load() 189 except (EOFError, cPickle.UnpicklingError): 190 raise FileResultReader.InvalidFile, \ 191 "file is not a pickled result stream" 192 193 if not isinstance(version, int): 194 # Version 0 file, no version number; in fact, we're 195 # holding a 'Result'. So we have no metadata to load and 196 # should just rewind. 197 self.file.seek(0) 198 self._ResetUnpickler() 199 elif version == 1: 200 self._ReadMetadata() 201 else: 202 raise QMException, "Unknown format version %i" % (version,)
203 204
205 - def _ResetUnpickler(self):
206 207 self.__unpickler = cPickle.Unpickler(self.file)
208 209
210 - def _ReadAddress(self):
211 212 raw = self.file.read(_int_size) 213 return struct.unpack(_int_format, raw)[0]
214 215
216 - def _ReadMetadata(self):
217 218 # We've read in the version number; next few bytes are the 219 # address of the first annotation. 220 addr = self._ReadAddress() 221 # That advanced the read head to the first 'Result'; save this 222 # spot to return to later. 223 first_result_addr = self.file.tell() 224 while addr: 225 # Go the the address. 226 self.file.seek(addr) 227 # First four bytes are the next address. 228 addr = self._ReadAddress() 229 # Then we restart the pickle stream... 230 self._ResetUnpickler() 231 # ...and read in the annotation here. 232 annotation_tuple = self.__unpickler.load() 233 kind = annotation_tuple[0] 234 if kind == "annotation": 235 (key, value) = annotation_tuple[1:] 236 self._annotations[key] = value 237 else: 238 print "Unknown annotation type '%s'; ignoring" % (kind,) 239 # Now loop back and jump to the next address. 240 241 # Finally, rewind back to the beginning for the reading of 242 # 'Result's. 243 self.file.seek(first_result_addr) 244 self._ResetUnpickler()
245 246
247 - def GetAnnotations(self):
248 249 return self._annotations
250 251
252 - def GetResult(self):
253 254 while 1: 255 try: 256 thing = self.__unpickler.load() 257 except (EOFError, cPickle.UnpicklingError): 258 # When reading from a StringIO, no EOFError will be 259 # raised when the unpickler tries to read from the file. 260 # Instead, the unpickler raises UnpicklingError when it 261 # tries to unpickle the empty string. 262 return None 263 else: 264 if thing is _annotation_sentinel: 265 # We're looking for results, but this is an annotation, 266 # so skip over it. 267 # By skipping past the address... 268 self.file.seek(_int_size, 1) 269 self._ResetUnpickler() 270 # ...and the annotation itself. 271 self.__unpickler.noload() 272 # Now loop. 273 else: 274 # We actually got a 'Result'. 275 return thing
276 277 ######################################################################## 278 # Local Variables: 279 # mode: python 280 # indent-tabs-mode: nil 281 # fill-column: 72 282 # End: 283

././@LongLink0000000000000000000000000000016500000000000011567 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_expectation_database.XMLExpectationDatabase-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_expectation_database.XMLExpectationDat0000664000076400007640000003637411122067150033300 0ustar stefanstefan qm.test.classes.xml_expectation_database.XMLExpectationDatabase
Package qm :: Package test :: Package classes :: Module xml_expectation_database :: Class XMLExpectationDatabase
[hide private]
[frames] | no frames]

Class XMLExpectationDatabase

source code

                          object --+        
                                   |        
                 extension.Extension --+    
                                       |    
expectation_database.ExpectationDatabase --+
                                           |
                                          XMLExpectationDatabase

An 'XMLExpectationDatabase' reads expectations from an XML file.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, **args)
Construct a new 'Extension'.
source code
 
Lookup(self, test_id)
Look up the expected outcome for the given test.
source code

Inherited from expectation_database.ExpectationDatabase: GetExpectedOutcomes

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  file_name = TextField()

Inherited from expectation_database.ExpectationDatabase: kind, test_database, testrun_parameters

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

Lookup(self, test_id)

source code 

Look up the expected outcome for the given test.

'test_id' -- test-id for which the outcome is queried.

returns -- a Result object associated with this test_id.

Overrides: expectation_database.ExpectationDatabase.Lookup
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.rsh_target.RSHTarget-class.html0000664000076400007640000005150511122067147030766 0ustar stefanstefan qm.test.classes.rsh_target.RSHTarget
Package qm :: Package test :: Package classes :: Module rsh_target :: Class RSHTarget
[hide private]
[frames] | no frames]

Class RSHTarget

source code

          object --+            
                   |            
 extension.Extension --+        
                       |        
           target.Target --+    
                           |    
process_target.ProcessTarget --+
                               |
                              RSHTarget

A target that runs tests via a remote shell invocation.

A 'RSHTarget' runs tests on a remote computer via a remote shell call. The remote shell is in the style of 'rsh' and 'ssh'. Using the remote shell, the target invokes the 'qmtest remote' script, which services commands sent via 'stdin', and replies via 'stdout'.

Nested Classes [hide private]

Inherited from process_target.ProcessTarget: QMTestExecutable

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, properties)
Construct a new 'RSHTarget'.
source code
 
_GetInterpreter(self)
Return the interpreter to use.
source code

Inherited from process_target.ProcessTarget: IsIdle, RunTest, Start, Stop

Inherited from target.Target: GetDatabase, GetGroup, GetName, IsInGroup

Inherited from target.Target (private): _BeginResourceSetUp, _CleanUpResource, _FinishResourceSetUp, _GetTemporaryDirectory, _RecordResult, _SetUpResource

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  host = qm.fields.TextField(title= "Remote Host Name", descript...
  remote_shell = qm.fields.TextField(title= "Remote Shell Progra...
  arguments = qm.fields.TextField(title= "Remote Shell Arguments...
A list of the arguments to the extension class.

Inherited from target.Target: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, properties)
(Constructor)

source code 

Construct a new 'RSHTarget'.

'database' -- The 'Database' containing the tests that will be run.

'properties' -- A dictionary mapping strings (property names) to strings (property values).

Overrides: object.__init__

_GetInterpreter(self)

source code 

Return the interpreter to use.

returns -- A list giving the path to an interpreter, and arguments to provide the interpreter. This interpreter is used to run QMTest. If '[]' is returned, then no intepreter is used.

Overrides: process_target.ProcessTarget._GetInterpreter
(inherited documentation)

Class Variable Details [hide private]

host

Value:
qm.fields.TextField(title= "Remote Host Name", description= """The nam\
e of the host on which to run tests.

            The name (or IP address) of the host on which QMTest
            should execute tests.  If this value is the empty string,
            the name of the target is used.""")

remote_shell

Value:
qm.fields.TextField(title= "Remote Shell Program", description= """The\
 path to the remote shell program.

            The name of the program that can be used to create a
            remote shell.  This program must accept the same command
            line arguments as the 'rsh' program.""", default_value= "s\
sh")

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
qm.fields.TextField(title= "Remote Shell Arguments", description= """T\
he arguments to provide to the remote shell.

            A space-separated list of arguments to provide to the
            remote shell program.""", default_value= "")

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command-pysrc.html0000664000076400007640000000732711122067161025022 0ustar stefanstefan qm.dist.command
Package qm :: Package dist :: Package command
[hide private]
[frames] | no frames]

Source Code for Package qm.dist.command

1   
2   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.QMTestReportPage-class.html0000664000076400007640000005117411122067151030061 0ustar stefanstefan qm.test.web.web.QMTestReportPage
Package qm :: Package test :: Package web :: Module web :: Class QMTestReportPage
[hide private]
[frames] | no frames]

Class QMTestReportPage

source code

web.DtmlPage --+    
               |    
 DefaultDtmlPage --+
                   |
                  QMTestReportPage

A 'QMTestReportPage' is a 'DtmlPage' for pages generated by QMTest.

A 'QMTestReportPage' automatically looks for DTML templates in the directory that contains QMTest DTML templates.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, dtml_template, server)
Construct a new 'QMTestReportPage'.
source code
 
GetRunDatabase(self)
Returns the 'RunDatabase' in use.
source code
 
GenerateStartBody(self, decorations=1)
Return markup to start the body of the HTML document.
source code
 
GenerateHtmlHeader(self, description, headers="")
Return the header for an HTML document.
source code
 
GetResultURL(self, id, kind)
Generate a URL for the result page for 'id'.
source code
 
FormatTimeIso(self, time) source code

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, dtml_template, server)
(Constructor)

source code 

Construct a new 'QMTestReportPage'.

'dtml_template' -- The file name of the DTML template, relative to the directory that contains QMTest DTML templates. (Usually, this is just a basename.)

'server' -- The 'QMTestServer' creating this page.

Overrides: web.DtmlPage.__init__

GetRunDatabase(self)

source code 

Returns the 'RunDatabase' in use.

returns -- The 'RunDatabase' in use.

GenerateStartBody(self, decorations=1)

source code 

Return markup to start the body of the HTML document.

Overrides: web.DtmlPage.GenerateStartBody
(inherited documentation)

GenerateHtmlHeader(self, description, headers="")

source code 

Return the header for an HTML document.

'description' -- A string describing this page.

'headers' -- Any additional HTML headers to place in the '<head>' section of the HTML document.

Overrides: web.DtmlPage.GenerateHtmlHeader

GetResultURL(self, id, kind)

source code 

Generate a URL for the result page for 'id'.

'id' -- The name of a test or resource.

'kind' -- either 'test' or 'resource'.

returns -- A url string for the result page for 'id'.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_HTML-module.html0000664000076400007640000001343611122067145031014 0ustar stefanstefan qm.external.DocumentTemplate.DT_HTML
Package qm :: Package external :: Package DocumentTemplate :: Module DT_HTML
[hide private]
[frames] | no frames]

Module DT_HTML

source code

HTML formated DocumentTemplates

$Id: DT_HTML.py 1007 2007-02-10 01:07:28Z stefan $

Classes [hide private]
  dtml_re_class
This needs to be replaced before 2.4.
  HTML
HTML Document Templates
  HTMLDefault
HTML document templates that edit themselves through copy.
  HTMLFile
HTML Document templates read from files.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Try-pysrc.html0000664000076400007640000022447011122067162030702 0ustar stefanstefan qm.external.DocumentTemplate.DT_Try
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Try
[hide private]
[frames] | no frames]

Source Code for Module qm.external.DocumentTemplate.DT_Try

  1  ############################################################################## 
  2  # 
  3  # Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved. 
  4  # 
  5  # This software is subject to the provisions of the Zope Public License, 
  6  # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution. 
  7  # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED 
  8  # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
  9  # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS 
 10  # FOR A PARTICULAR PURPOSE 
 11  # 
 12  ############################################################################## 
 13   
 14  import  sys, traceback 
 15  from cStringIO import StringIO 
 16  from DT_Util import ParseError, parse_params, render_blocks 
 17  from DT_Util import namespace, InstanceDict 
 18  from DT_Return import DTReturn 
 19   
20 -class Try:
21 """Zope DTML Exception handling 22 23 usage: 24 25 <!--#try--> 26 <!--#except SomeError AnotherError--> 27 <!--#except YetAnotherError--> 28 <!--#except--> 29 <!--#else--> 30 <!--#/try--> 31 32 or: 33 34 <!--#try--> 35 <!--#finally--> 36 <!--#/try--> 37 38 The DTML try tag functions quite like Python's try command. 39 40 The contents of the try tag are rendered. If an exception is raised, 41 then control switches to the except blocks. The first except block to 42 match the type of the error raised is rendered. If an except block has 43 no name then it matches all raised errors. 44 45 The try tag understands class-based exceptions, as well as string-based 46 exceptions. Note: the 'raise' tag raises string-based exceptions. 47 48 Inside the except blocks information about the error is available via 49 three variables. 50 51 'error_type' -- This variable is the name of the exception caught. 52 53 'error_value' -- This is the caught exception's value. 54 55 'error_tb' -- This is a traceback for the caught exception. 56 57 The optional else block is rendered when no exception occurs in the 58 try block. Exceptions in the else block are not handled by the preceding 59 except blocks. 60 61 The try..finally form specifies a `cleanup` block, to be rendered even 62 when an exception occurs. Note that any rendered result is discarded if 63 an exception occurs in either the try or finally blocks. The finally block 64 is only of any use if you need to clean up something that will not be 65 cleaned up by the transaction abort code. 66 67 The finally block will always be called, wether there was an exception in 68 the try block or not, or wether or not you used a return tag in the try 69 block. Note that any output of the finally block is discarded if you use a 70 return tag in the try block. 71 72 If an exception occurs in the try block, and an exception occurs in the 73 finally block, or you use the return tag in that block, any information 74 about that first exception is lost. No information about the first 75 exception is available in the finally block. Also, if you use a return tag 76 in the try block, and an exception occurs in the finally block or you use 77 a return tag there as well, the result returned in the try block will be 78 lost. 79 80 Original version by Jordan B. Baker. 81 82 Try..finally and try..else implementation by Martijn Pieters. 83 """ 84 85 name = 'try' 86 blockContinuations = 'except', 'else', 'finally' 87 finallyBlock=None 88 elseBlock=None 89
90 - def __init__(self, blocks):
91 tname, args, section = blocks[0] 92 93 self.args = parse_params(args) 94 self.section = section.blocks 95 96 97 # Find out if this is a try..finally type 98 if len(blocks) == 2 and blocks[1][0] == 'finally': 99 self.finallyBlock = blocks[1][2].blocks 100 101 # This is a try [except]* [else] block. 102 else: 103 # store handlers as tuples (name,block) 104 self.handlers = [] 105 defaultHandlerFound = 0 106 107 for tname,nargs,nsection in blocks[1:]: 108 if tname == 'else': 109 if not self.elseBlock is None: 110 raise ParseError, ( 111 'No more than one else block is allowed', 112 self.name) 113 self.elseBlock = nsection.blocks 114 115 elif tname == 'finally': 116 raise ParseError, ( 117 'A try..finally combination cannot contain ' 118 'any other else, except or finally blocks', 119 self.name) 120 121 else: 122 if not self.elseBlock is None: 123 raise ParseError, ( 124 'The else block should be the last block ' 125 'in a try tag', self.name) 126 127 for errname in nargs.split(): 128 self.handlers.append((errname,nsection.blocks)) 129 if nargs.strip()=='': 130 if defaultHandlerFound: 131 raise ParseError, ( 132 'Only one default exception handler ' 133 'is allowed', self.name) 134 else: 135 defaultHandlerFound = 1 136 self.handlers.append(('',nsection.blocks))
137
138 - def render(self, md):
139 if (self.finallyBlock is None): 140 return self.render_try_except(md) 141 else: 142 return self.render_try_finally(md)
143
144 - def render_try_except(self, md):
145 result = '' 146 147 # first we try to render the first block 148 try: 149 result = render_blocks(self.section, md) 150 except DTReturn: 151 raise 152 except: 153 # but an error occurs.. save the info. 154 t,v = sys.exc_info()[:2] 155 if type(t)==type(''): 156 errname = t 157 else: 158 errname = t.__name__ 159 160 handler = self.find_handler(t) 161 162 if handler is None: 163 # we didn't find a handler, so reraise the error 164 raise 165 166 # found the handler block, now render it 167 try: 168 f=StringIO() 169 traceback.print_exc(100,f) 170 error_tb=f.getvalue() 171 ns = namespace(md, error_type=errname, error_value=v, 172 error_tb=error_tb)[0] 173 md._push(InstanceDict(ns,md)) 174 return render_blocks(handler, md) 175 finally: 176 md._pop(1) 177 178 else: 179 # No errors have occured, render the optional else block 180 if (self.elseBlock is None): 181 return result 182 else: 183 return result + render_blocks(self.elseBlock, md)
184
185 - def render_try_finally(self, md):
186 result = '' 187 # first try to render the first block 188 try: 189 result = render_blocks(self.section, md) 190 # Then handle finally block 191 finally: 192 result = result + render_blocks(self.finallyBlock, md) 193 return result
194
195 - def find_handler(self,exception):
196 "recursively search for a handler for a given exception" 197 if type(exception)==type(''): 198 for e,h in self.handlers: 199 if exception==e or e=='': 200 return h 201 else: 202 return None 203 for e,h in self.handlers: 204 if e==exception.__name__ or e=='' or self.match_base(exception,e): 205 return h 206 return None
207
208 - def match_base(self,exception,name):
209 for base in exception.__bases__: 210 if base.__name__==name or self.match_base(base,name): 211 return 1 212 return None
213 214 __call__ = render
215

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.base-module.html0000664000076400007640000010462511122067145024460 0ustar stefanstefan qm.test.base
Package qm :: Package test :: Module base
[hide private]
[frames] | no frames]

Module base

source code

Classes [hide private]
  CouldNotLoadExtensionError
An exception indicating that an extension class could not be loaded.
Functions [hide private]
 
get_extension_directories(kind, database, database_path=None)
Return the directories to search for QMTest extensions.
source code
 
get_extension_class_names_in_directory(directory)
Return the names of QMTest extension classes in 'directory'.
source code
 
get_extension_class_names(kind, database, database_path=None)
Return the names of extension classes.
source code
 
get_extension_class_from_directory(class_name, kind, directory, path)
Load an extension class from 'directory'.
source code
 
get_extension_class(class_name, kind, database, database_path=None)
Return the extension class named 'class_name'.
source code
 
get_test_class(class_name, database)
Return the test class named 'class_name'.
source code
 
get_resource_class(class_name, database)
Return the resource class named 'class_name'.
source code
 
get_extension_classes(kind, database=None)
Return the extension classes for the given 'kind'.
source code
 
load_results(file, database)
Read test results from a file.
source code
 
load_expectations(file, database, annotations=None)
Read expectations from a file.
source code
 
load_outcomes(file, database)
Load test outcomes from a file.
source code
 
_result_from_dom(node)
Extract a result from a DOM node.
source code
Variables [hide private]
  __extension_bases = {'database': qm.test.database.Database, 'h...
A map from extension class kinds to base classes.
  extension_kinds = __extension_bases.keys()
Names of different kinds of QMTest extension classes.
  __class_caches = {}
A dictionary of loaded class caches.
Function Details [hide private]

get_extension_directories(kind, database, database_path=None)

source code 
Return the directories to search for QMTest extensions.

'kind' -- A string giving kind of extension for which we are looking.
This must be of the elements of 'extension_kinds'.

'database' -- The 'Database' with which the extension class will be
used, or 'None'.

'database_path' -- The path from which the database will be loaded.
If 'None', 'database.GetPath()' is used.

returns -- A sequence of strings.  Each string is the path to a
directory that should be searched for QMTest extensions.  The
directories must be searched in order; the first directory
containing the desired module is the one from which the module is
loaded.

The directories that are returned are, in order:

1. Those directories present in the 'QMTEST_CLASS_PATH' environment
   variable.

2. Those directories specified by the 'GetClassPaths' method on the
   test database -- unless 'kind' is 'database'.

3. The directory specified by config.extension_path.

4. The directories containing classes that come with QMTest.

By placing the 'QMTEST_CLASS_PATH' directories first, users can
override test classes with standard names.

get_extension_class_names_in_directory(directory)

source code 

Return the names of QMTest extension classes in 'directory'.

'directory' -- A string giving the path to a directory in the file system.

returns -- A dictionary mapping the strings in 'extension_kinds' to sequences of strings. Each element in the sequence names an extension class, using the form 'module.class'

get_extension_class_names(kind, database, database_path=None)

source code 

Return the names of extension classes.

'kind' -- The kind of extension class. This value must be one of the 'extension_kinds'.

'database' -- The 'Database' with which the extension class will be used, or 'None' if 'kind' is 'database'.

'database_path' -- The path from which the database will be loaded. If 'None', 'database.GetPath()' is used.

returns -- A sequence of strings giving the names of the extension classes with the indicated 'kind', in the form 'module.class'.

get_extension_class_from_directory(class_name, kind, directory, path)

source code 

Load an extension class from 'directory'.

'class_name' -- The name of the extension class, in the form 'module.class'.

'kind' -- The kind of class to load. This value must be one of the 'extension_kinds'.

'directory' -- The directory from which to load the class.

'path' -- The directories to search for modules imported by the new module.

returns -- The class loaded.

get_extension_class(class_name, kind, database, database_path=None)

source code 

Return the extension class named 'class_name'.

'class_name' -- The name of the class, in the form 'module.class'.

'kind' -- The kind of class to load. This value must be one of the 'extension_kinds'.

'database' -- The 'Database' with which the extension class will be used, or 'None' if 'kind' is 'database'.

'database_path' -- The path from which the database will be loaded. If 'None', 'database.GetPath()' is used.

returns -- The class object with the indicated 'class_name'.

get_test_class(class_name, database)

source code 

Return the test class named 'class_name'.

'class_name' -- The name of the test class, in the form 'module.class'.

returns -- The test class object with the indicated 'class_name'.

get_resource_class(class_name, database)

source code 

Return the resource class named 'class_name'.

'class_name' -- The name of the resource class, in the form 'module.class'.

returns -- The resource class object with the indicated 'class_name'.

get_extension_classes(kind, database=None)

source code 

Return the extension classes for the given 'kind'.

'kind' -- The kind of extensions being sought. The value must be one of the 'extension_kinds'.

'database' -- If not 'None', the test 'Database' in use.

returns -- A list of the available extension classes of the indicated 'kind'.

load_results(file, database)

source code 

Read test results from a file.

'file' -- The filename or file object from which to read the results. If 'file' is not a string, then it is must be a seekable file object, and this function will look for a 'FileResultReader' that accepts the file. If 'file' is a string, then it is treated as either a filename or as an extension descriptor.

'database' -- The current database.

returns -- A 'ResultReader' object, or raises an exception if no appropriate reader is available.

load_expectations(file, database, annotations=None)

source code 

Read expectations from a file.

'file' -- The filename or file object from which to read the expectations. If 'file' is not a string, then it is must be a seekable file object, and this function will look for an 'ExpectationDatabase' that accepts the file. If 'file' is a string, then it is treated as either a filename or as an extension descriptor.

'database' -- The current database.

'annotations' -- Annotations for the current test run.

returns -- An 'ExpectationDatabase' object, or raises an exception if no appropriate reader is available.

load_outcomes(file, database)

source code 

Load test outcomes from a file.

'file' -- The file object from which to read the results. See 'load_results' for details.

'database' -- The current database.

returns -- A map from test IDs to outcomes.

_result_from_dom(node)

source code 

Extract a result from a DOM node.

'node' -- A DOM node corresponding to a "result" element.

returns -- A 'Result' object. The context for the result is 'None', since context is not represented in a result DOM node.


Variables Details [hide private]

__extension_bases

A map from extension class kinds to base classes.

An extension class of a particular 'kind' must be derived from 'extension_bases[kind]'.

Value:
{'database': qm.test.database.Database, 'host': qm.host.Host, 'label':\
 qm.label.Label, 'resource': qm.test.resource.Resource, 'result_reader\
': qm.test.result_reader.ResultReader, 'result_stream': qm.test.result\
_stream.ResultStream, 'run_database': qm.test.run_database.RunDatabase\
, 'expectation_database': qm.test.expectation_database.ExpectationData\
base, 'suite': qm.test.suite.Suite, 'target': qm.test.target.Target, '\
test': qm.test.test.Test}

__class_caches

A dictionary of loaded class caches.

The keys are the kinds in 'extension_kinds'. The associated value is itself a dictionary mapping class names to class objects.

Value:
{}

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.command_host-module.html0000664000076400007640000000214011122067144030424 0ustar stefanstefan command_host

Module command_host


Classes

CommandHost

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.file_result_stream-module.html0000664000076400007640000001120111122067145027421 0ustar stefanstefan qm.test.file_result_stream
Package qm :: Package test :: Module file_result_stream
[hide private]
[frames] | no frames]

Module file_result_stream

source code

Classes [hide private]
  FileResultStream
A 'FileResultStream' writes its output to a file.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.ssh_host-module.html0000664000076400007640000001176411122067145027035 0ustar stefanstefan qm.test.classes.ssh_host
Package qm :: Package test :: Package classes :: Module ssh_host
[hide private]
[frames] | no frames]

Module ssh_host

source code

Classes [hide private]
  SSHHost
An 'SSHHost' is accessible via 'ssh' or a similar program.
  RSHHost
An 'RSHHost' is an 'SSHHost' that uses 'rsh' instead of 'ssh'.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_Var-module.html0000664000076400007640000000744511122067144031565 0ustar stefanstefan DT_Var

Module DT_Var


Classes

Call
Comment
Var

Functions

dollars_and_cents
dollars_and_cents_with_commas
len_comma
len_format
newline_to_br
spacify
sql_quote
structured_text
thousands_commas
url_quote
url_quote_plus
url_unquote
url_unquote_plus
whole_dollars
whole_dollars_with_commas

Variables

StructuredText
__doc__
__rcs_id__
modifiers
special_formats

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Return-module.html0000664000076400007640000001205211122067145031520 0ustar stefanstefan qm.external.DocumentTemplate.DT_Return
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Return
[hide private]
[frames] | no frames]

Module DT_Return

source code


Version: 1069

Classes [hide private]
  ReturnTag
  DTReturn
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_test.DejaGNUTest-class.html0000664000076400007640000013324611122067147031555 0ustar stefanstefan qm.test.classes.dejagnu_test.DejaGNUTest
Package qm :: Package test :: Package classes :: Module dejagnu_test :: Class DejaGNUTest
[hide private]
[frames] | no frames]

Class DejaGNUTest

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
                  test.Test --+
                              |
   dejagnu_base.DejaGNUBase --+
                              |
                             DejaGNUTest

A 'DejaGNUTest' emulates a DejaGNU test.

See 'framework.exp' in the DejaGNU distribution for more information.

Nested Classes [hide private]
  BuildExecutable
A 'BuildExecutable' runs on the build machine.

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
_GetTargetEnvironment(self, context)
Return additional environment variables to set on the target.
source code
 
_RunBuildExecutable(self, context, result, file, args=[], dir=None)
Run 'file' on the target.
source code
 
_RunTargetExecutable(self, context, result, file)
Run 'file' on the target.
source code
 
_RecordDejaGNUOutcome(self, result, outcome, message, expectation=None)
Record a DejaGNU outcome.
source code
 
_Unresolved(self, result, message)
Record an 'unresolved' DejaGNU outcome.
source code
 
_Error(self, message)
Raise an exception indicating an error in the test.
source code
 
_GetSourcePath(self)
Return the path to the primary source file.
source code
 
_GetBuild(self, context)
Return the GNU triplet corresponding to the build machine.
source code
 
_GetTarget(self, context)
Return the GNU triplet corresponding to the target machine.
source code
 
_IsNative(self, context)
Returns true if the build and target machines are the same.
source code
 
_SetUp(self, context)
Prepare to run a test.
source code
 
_ParseTclWords(self, s, variables={})
Separate 's' into words, in the same way that Tcl would.
source code

Inherited from test.Test: GetTargetGroup, Run

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Inherited from dejagnu_base.DejaGNUBase (private): _RecordCommand, _RecordCommandOutput

Class Variables [hide private]
  arguments = [qm.fields.AttachmentField(name= "source_file", ti...
A list of the arguments to the extension class.
  PASS = "PASS"
  FAIL = "FAIL"
  KFAIL = "KFAIL"
  KPASS = "KPASS"
  XPASS = "XPASS"
  XFAIL = "XFAIL"
  WARNING = "WARNING"
  ERROR = "ERROR"
  UNTESTED = "UNTESTED"
  UNRESOLVED = "UNRESOLVED"
  UNSUPPORTED = "UNSUPPORTED"
  dejagnu_outcomes = PASS, FAIL, XPASS, XFAIL, WARNING, ERROR, U...
The DejaGNU test outcomes.
  outcome_map = {PASS: Result.PASS, FAIL: Result.FAIL, KFAIL: Re...
A map from DejaGNU outcomes to QMTest outcomes.
  executable_timeout = 300
The number of seconds a program is permitted to run on the target.
  RESULT_PREFIX = "DejaGNUTest.result_"
The prefix for DejaGNU result annotations.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

_GetTargetEnvironment(self, context)

source code 

Return additional environment variables to set on the target.

'context' -- The 'Context' in which this test is running.

returns -- A map from strings (environment variable names) to strings (values for those variables). These new variables are added to the environment when a program executes on the target.

_RunBuildExecutable(self, context, result, file, args=[], dir=None)

source code 

Run 'file' on the target.

'context' -- The 'Context' in which this test is running.

'result' -- The 'Result' of this test.

'file' -- The path to the executable file.

'args' -- The arguments to the 'file'.

'dir' -- The directory in which the program should execute.

returns -- A pair '(status, output)'. The 'status' is the exit status from the command; the 'output' is the combined results of the standard output and standard error streams.

_RunTargetExecutable(self, context, result, file)

source code 

Run 'file' on the target.

'context' -- The 'Context' in which this test is running.

'result' -- The 'Result' of this test.

'file' -- The path to the executable file.

returns -- One of the 'dejagnu_outcomes'.

_RecordDejaGNUOutcome(self, result, outcome, message, expectation=None)

source code 

Record a DejaGNU outcome.

'result' -- A 'Result' object.

'outcome' -- One of the 'dejagnu_outcomes'.

'message' -- A string, explaining the outcome.

'expectation' -- If not 'None, the DejaGNU outcome that was expected.

_Unresolved(self, result, message)

source code 

Record an 'unresolved' DejaGNU outcome.

This function is identical to 'RecordDejaGNUOutcome', except that the 'outcome' is always 'UNRESOLVED'.

_Error(self, message)

source code 

Raise an exception indicating an error in the test.

'message' -- A description of the problem.

This function is used when the original Tcl code in DejaGNU would have used the Tcl 'error' primitive. These situations indicate problems with the test itself, such as incorrect usage of special test commands.

_GetSourcePath(self)

source code 

Return the path to the primary source file.

returns -- A string giving the path to the primary source file.

_GetBuild(self, context)

source code 

Return the GNU triplet corresponding to the build machine.

'context' -- The 'Context' in which the test is running.

returns -- The GNU triplet corresponding to the target machine, i.e,. the machine on which the compiler will run.

_GetTarget(self, context)

source code 

Return the GNU triplet corresponding to the target machine.

'context' -- The 'Context' in which the test is running.

returns -- The GNU triplet corresponding to the target machine, i.e,. the machine on which the programs generated by the compiler will run.

_IsNative(self, context)

source code 

Returns true if the build and target machines are the same.

'context' -- The 'Context' in which this test is running.

returns -- True if this test is runing "natively", i.e., if the build and target machines are the same.

_SetUp(self, context)

source code 

Prepare to run a test.

'context' -- The 'Context' in which this test will run.

This method may be overridden by derived classes, but they must call this version.

Overrides: dejagnu_base.DejaGNUBase._SetUp

_ParseTclWords(self, s, variables={})

source code 

Separate 's' into words, in the same way that Tcl would.

's' -- A string.

'variables' -- A map from variable names to values. If Tcl variable substitutions are encountered in 's', the corresponding value from 'variables' will be used.

returns -- A sequence of strings, each of which is a Tcl word.

Command substitution is not supported and results in an exceptions. Invalid inputs (like the string consisting of a single quote) also result in exceptions.

See 'Tcl and the Tk Toolkit', by John K. Ousterhout, copyright 1994 by Addison-Wesley Publishing Company, Inc. for details about the syntax of Tcl.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.AttachmentField(name= "source_file", title= "Source File", \
description= """The source file."""),]

dejagnu_outcomes

The DejaGNU test outcomes.

Value:
PASS, FAIL, XPASS, XFAIL, WARNING, ERROR, UNTESTED, UNRESOLVED, UNSUPP\
ORTED

outcome_map

A map from DejaGNU outcomes to QMTest outcomes.

Value:
{PASS: Result.PASS, FAIL: Result.FAIL, KFAIL: Result.FAIL, KPASS: Resu\
lt.PASS, XPASS: Result.PASS, XFAIL: Result.FAIL, WARNING: Result.PASS,\
 ERROR: Result.ERROR, UNTESTED: Result.UNTESTED, UNRESOLVED: Result.UN\
TESTED, UNSUPPORTED: Result.UNTESTED}

RESULT_PREFIX

The prefix for DejaGNU result annotations.

All results that would be generated by DejaGNU are inserted into the QMTest result as annotations beginning with this prefix. The prefix is followed by an 1-indexed integer; earlier results are inserted with lower numbers.

Value:
"DejaGNUTest.result_"

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.simulator-module.html0000664000076400007640000001125411122067145027214 0ustar stefanstefan qm.test.classes.simulator
Package qm :: Package test :: Package classes :: Module simulator
[hide private]
[frames] | no frames]

Module simulator

source code

Classes [hide private]
  Simulator
A 'Simulator' is a semi-hosted simulation environment.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.dejagnu_test-module.html0000664000076400007640000000214011122067144030425 0ustar stefanstefan dejagnu_test

Module dejagnu_test


Classes

DejaGNUTest

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Let-module.html0000664000076400007640000002121411122067145030765 0ustar stefanstefan qm.external.DocumentTemplate.DT_Let
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Let
[hide private]
[frames] | no frames]

Module DT_Let

source code

The Let tag was contributed to Zope by and is copyright, 1999
 Phillip J. Eby.  Permission has been granted to release the Let tag
 under the Zope Public License.


Let name=value...

The 'let' tag is used to bind variables to values within a block.

The text enclosed in the let tag is rendered using information
from the given variables or expressions.

For example::

  <!--#let foofunc="foo()" my_bar=bar-->
    foo() = <!--#var foofunc-->,
    bar = <!--#var my_bar-->
  <!--#/let-->

Notice that both 'name' and 'expr' style attributes may be used to
specify data.  'name' style attributes (e.g. my_bar=bar) will be
rendered as they are for var/with/in/etc.  Quoted attributes will
be treated as Python expressions.

Variables are processed in sequence, so later assignments can
reference and/or overwrite the results of previous assignments,
as desired.

Classes [hide private]
  Let
Functions [hide private]
 
parse_let_params(text, result=None, tag='let', parmre=re.compile(r'([\x00- ]*([^\x00- ="]+)=([^\x00- ="]+))'), qparmre=re.compile(r'([\x00- ]*([^\x00- ="]+)="([^"]*)")'), **parms) source code
qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-S.html0000664000076400007640000011716311122067144024320 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

S



qmtest-2.4.1/share/doc/qmtest/html/manual/qm-pysrc.html0000664000076400007640000003553011122067152022440 0ustar stefanstefan qm
Package qm
[hide private]
[frames] | no frames]

Source Code for Package qm

 1  ######################################################################## 
 2  # 
 3  # File:   __init__.py 
 4  # Author: Alex Samuel 
 5  # Date:   2000-12-20 
 6  # 
 7  # Contents: 
 8  #   Initialization for module qm. 
 9  # 
10  # Copyright (c) 2000 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from qm.common import * 
21  from qm.diagnostic import error, warning, message 
22  from qm.config import version 
23  from qm.config import data_dir 
24  from qm.config import doc_dir 
25  from qm.config import extension_path 
26  # The prefix variable is only available after QMTest is built. 
27  # Compute it, if it isn't available. 
28  try: 
29      from qm.config import prefix 
30  except ImportError: 
31      import os 
32      prefix = os.path.join(os.path.dirname(__file__), os.path.pardir) 
33   
34  version_info = tuple(version.split('.')) 
35   
36  ######################################################################## 
37  # Local Variables: 
38  # mode: python 
39  # indent-tabs-mode: nil 
40  # End: 
41   

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.structured_text-module.html0000664000076400007640000000633611122067144026622 0ustar stefanstefan structured_text

Module structured_text


Classes

Formatter
HtmlFormatter
StructuredTextProcessor
TextFormatter

Functions

escape_html_entities
get_first
get_first_paragraph
get_paragraphs
get_rest
to_html
to_text

Variables

character
entity
html_help_text

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result.Result-class.html0000664000076400007640000013621011122067150026150 0ustar stefanstefan qm.test.result.Result
Package qm :: Package test :: Module result :: Class Result
[hide private]
[frames] | no frames]

Class Result

source code

A 'Result' describes the outcome of a test.

A 'Result' contains two pieces of data: an outcome and a set of annotations. The outcome indicates whether the test passed or failed. More specifically, the outcome may be one of the following constants:

'Result.PASS' -- The test passed.

'Result.FAIL' -- The test failed.

'Result.ERROR' -- Something went wrong in the process of trying to execute the test. For example, if the Python code implementing the 'Run' method in the test class raised an exception, the outcome would be 'Result.ERROR'.

'Result.UNTESTED' -- QMTest did not even try to run the test. For example, if a prerequiste was not satisfied, then this outcome will be used.'

The annotations are a dictionary, mapping strings to strings.

The indices should be of the form 'class.name' where 'class' is the name of the test class that created the annotation. Any annotations created by QMTest, as opposed to the test class, will have indices of the form 'qmtest.name'.

The annotation values are HTML. When displayed in the GUI, the HTML is inserted directly into the result page; when the command-line interface is used the HTML is converted to plain text.

Currently, QMTest recognizes the following built-in annotations:

'Result.CAUSE' -- For results whose outcome is not 'FAIL', this annotation gives a brief description of why the test failed. The preferred form of this message is a phrase like "Incorrect output." or "Exception thrown." The message should begin with a capital letter and end with a period. Most results formatters will display this information prominently.

'Result.EXCEPTION' -- If an exeption was thrown during the test execution, a brief description of the exception.

'Result.TARGET' -- This annotation indicates on which target the test was executed.

'Result.TRACEBACK' -- If an exeption was thrown during the test execution, a representation of the traceback indicating where the exception was thrown.

A 'Result' object has methods that allow it to act as a dictionary from annotation names to annotation values. You can directly add an annotation to a 'Result' by writing code of the form 'result[CAUSE] = "Exception thrown."'.

A 'Result' object is also used to describe the outcome of executing either setup or cleanup phase of a 'Resource'.

Instance Methods [hide private]
 
__init__(self, kind, id, outcome='PASS', annotations={})
Construct a new 'Result'.
source code
 
__getstate__(self)
Return a representation of this result for pickling.
source code
 
__setstate__(self, pickled_state)
Construct a 'Result' from its pickled form.
source code
 
GetKind(self)
Return the kind of result this is.
source code
 
GetOutcome(self)
Return the outcome associated with the test.
source code
 
SetOutcome(self, outcome, cause=None, annotations={})
Set the outcome associated with the test.
source code
 
Annotate(self, annotations)
Add 'annotations' to the current set of annotations.
source code
 
Fail(self, cause=None, annotations={})
Mark the test as failing.
source code
 
GetId(self)
Return the label for the test or resource.
source code
 
GetCause(self)
Return the cause of failure, if the test failed.
source code
 
SetCause(self, cause)
Set the cause of failure.
source code
 
Quote(self, string)
Return a version of string suitable for an annotation value.
source code
 
NoteException(self, exc_info=None, cause=None, outcome='ERROR')
Note that an exception occurred during execution.
source code
 
CheckExitStatus(self, prefix, desc, status, non_zero_exit_ok=0)
Check the exit status from a command.
source code
 
MakeDomNode(self, document)
Generate a DOM element node for this result.
source code
 
__getitem__(self, key) source code
 
__setitem__(self, key, value) source code
 
__delitem__(self, key) source code
 
get(self, key, default=None) source code
 
has_key(self, key) source code
 
keys(self) source code
 
items(self) source code
Class Variables [hide private]
  RESOURCE_SETUP = 'resource_setup'
  RESOURCE_CLEANUP = 'resource_cleanup'
  TEST = 'test'
  FAIL = 'FAIL'
  ERROR = 'ERROR'
  UNTESTED = 'UNTESTED'
  PASS = 'PASS'
  CAUSE = 'qmtest.cause'
  EXCEPTION = 'qmtest.exception'
  RESOURCE = 'qmtest.resource'
  TARGET = 'qmtest.target'
  TRACEBACK = 'qmtest.traceback'
  START_TIME = 'qmtest.start_time'
  END_TIME = 'qmtest.end_time'
  kinds = ['resource_setup', 'resource_cleanup', 'test']
A list of the possible kinds.
  outcomes = ['ERROR', 'FAIL', 'UNTESTED', 'PASS']
A list of the possible outcomes.
Method Details [hide private]

__init__(self, kind, id, outcome='PASS', annotations={})
(Constructor)

source code 

Construct a new 'Result'.

'kind' -- The kind of result. The value must be one of the 'Result.kinds'.

'id' -- The label for the test or resource to which this result corresponds.

'outcome' -- The outcome associated with the test. The value must be one of the 'Result.outcomes'.

'annotations' -- The annotations associated with the test.

__getstate__(self)

source code 

Return a representation of this result for pickling.

By using an explicit tuple representation of 'Result's when storing them in a pickle file, we decouple our storage format from internal implementation details (e.g., the names of private variables).

GetKind(self)

source code 

Return the kind of result this is.

returns -- The kind of entity (one of the 'kinds') to which this result corresponds.

GetOutcome(self)

source code 

Return the outcome associated with the test.

returns -- The outcome associated with the test. This value will be one of the 'Result.outcomes'.

SetOutcome(self, outcome, cause=None, annotations={})

source code 

Set the outcome associated with the test.

'outcome' -- One of the 'Result.outcomes'.

'cause' -- If not 'None', this value becomes the value of the 'Result.CAUSE' annotation.

'annotations' -- The annotations are added to the current set of annotations.

Fail(self, cause=None, annotations={})

source code 

Mark the test as failing.

'cause' -- If not 'None', this value becomes the value of the 'Result.CAUSE' annotation.

'annotations' -- The annotations are added to the current set of annotations.

GetId(self)

source code 

Return the label for the test or resource.

returns -- A label indicating indicating to which test or resource this result corresponds.

GetCause(self)

source code 

Return the cause of failure, if the test failed.

returns -- If the test failed, return the cause of the failure, if available.

SetCause(self, cause)

source code 

Set the cause of failure.

'cause' -- A string indicating the cause of failure. Like all annotations, 'cause' will be interested as HTML.

Quote(self, string)

source code 

Return a version of string suitable for an annotation value.

Performs appropriate quoting for a string that should be taken verbatim; this includes HTML entity escaping, and addition of <pre> tags.

'string' -- The verbatim string to be quoted.

returns -- The quoted string.

NoteException(self, exc_info=None, cause=None, outcome='ERROR')

source code 

Note that an exception occurred during execution.

'exc_info' -- A triple, in the same form as that returned from 'sys.exc_info'. If 'None', the value of 'sys.exc_info()' is used instead.

'cause' -- The value of the 'Result.CAUSE' annotation. If 'None', a default message is used.

'outcome' -- The outcome of the test, now that the exception has occurred.

A test class can call this method if an exception occurs while the test is being run.

CheckExitStatus(self, prefix, desc, status, non_zero_exit_ok=0)

source code 

Check the exit status from a command.

'prefix' -- The prefix that should be used when creating result annotations.

'desc' -- A description of the executing program.

'status' -- The exit status, as returned by 'waitpid'.

'non_zero_exit_ok' -- True if a non-zero exit code is not considered failure.

returns -- False if the test failed, true otherwise.

MakeDomNode(self, document)

source code 

Generate a DOM element node for this result.

Note that the context is not represented in the DOM node.

'document' -- The containing DOM document.

returns -- The element created.


Class Variable Details [hide private]

outcomes

A list of the possible outcomes.

The order of the 'outcomes' is significant; they are ordered from most interesting to least interesting from the point of view of someone browsing results.

Value:
['ERROR', 'FAIL', 'UNTESTED', 'PASS']

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DTtestExpr-module.html0000664000076400007640000002232011122067145031717 0ustar stefanstefan qm.external.DocumentTemplate.DTtestExpr
Package qm :: Package external :: Package DocumentTemplate :: Module DTtestExpr
[hide private]
[frames] | no frames]

Module DTtestExpr

source code

short description

$Id: DTtestExpr.py 1069 2008-11-13 21:55:43Z stefan $


Version: 1069

Functions [hide private]
 
test1() source code
 
test2() source code
 
test3() source code
 
test4() source code
Variables [hide private]
  __doc__ = '''short descript...
Variables Details [hide private]

__doc__

Value:
'''short description


$Id: DTtestExpr.py 1069 2008-11-13 21:55:43Z stefan $'''

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.command_thread-module.html0000664000076400007640000001114711122067145026507 0ustar stefanstefan qm.test.command_thread
Package qm :: Package test :: Module command_thread
[hide private]
[frames] | no frames]

Module command_thread

source code

Classes [hide private]
  CommandThread
A 'CommandThread' is a thread that executes commands.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_thread-pysrc.html0000664000076400007640000020301311122067154026742 0ustar stefanstefan qm.test.execution_thread
Package qm :: Package test :: Module execution_thread
[hide private]
[frames] | no frames]

Source Code for Module qm.test.execution_thread

  1  ######################################################################## 
  2  # 
  3  # File:   execution_thread.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2001-08-04 
  6  # 
  7  # Contents: 
  8  #   Code for coordinating the running of tests. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import os 
 21  import qm.common 
 22  from   qm.test.base import * 
 23  from   qm.test.context import * 
 24  from   qm.test.execution_engine import * 
 25  import qm.xmlutil 
 26  import Queue 
 27  from   result import * 
 28  import sys 
 29  from   threading import * 
 30   
 31  ######################################################################## 
 32  # Classes 
 33  ######################################################################## 
 34   
35 -class ExecutionThread(Thread, ExecutionEngine):
36 """A 'ExecutionThread' executes tests in a separate thread. 37 38 A 'ExecutionThread' is an 'ExecutionEngine' that runs tests in a 39 separate thread. 40 41 This class schedules the tests, plus the setup and cleanup of any 42 resources they require, across one or more targets. 43 44 The shedule is determined dynamically as the tests are executed 45 based on which targets are idle and which are not. Therefore, the 46 testing load should be reasonably well balanced, even across a 47 heterogeneous network of testing machines.""" 48
49 - def __init__(self, 50 database, 51 test_ids, 52 context, 53 targets, 54 result_streams = None, 55 expectations = None):
56 """Set up a test run. 57 58 'database' -- The 'Database' containing the tests that will be 59 run. 60 61 'test_ids' -- A sequence of IDs of tests to run. Where 62 possible, the tests are started in the order specified. 63 64 'context' -- The context object to use when running tests. 65 66 'targets' -- A sequence of 'Target' objects, representing 67 targets on which tests may be run. 68 69 'result_streams' -- A sequence of 'ResultStream' objects. Each 70 stream will be provided with results as they are available. 71 This thread will not perform any locking of these streams as 72 they are written to; each stream must provide its own 73 synchronization if it will be accessed before 'run' returns. 74 75 'expectations' -- If not 'None', a dictionary mapping test IDs 76 to expected outcomes.""" 77 78 Thread.__init__(self, None, None, None) 79 ExecutionEngine.__init__(self, database, test_ids, context, 80 targets, result_streams, expectations) 81 82 # This is a deamon thread; if the main QMTest thread exits, 83 # this thread should not prolong the life of the process. 84 # Because the daemon flag is inherited from the creating thread, 85 # threads created by the targets will automatically be daemon 86 # threads. 87 self.setDaemon(1) 88 89 # Access to __terminated is guarded with this lock. 90 self.__lock = Lock()
91 92
93 - def run(self):
94 """Run the tests. 95 96 This method runs the tests specified in the __init__ 97 function.""" 98 self.Run()
99 100
101 - def RequestTermination(self):
102 """Request termination. 103 104 Request that the execution thread be terminated. This may 105 take some time; tests that are already running will continue 106 to run, for example.""" 107 108 self.__lock.acquire() 109 ExecutionEngine.RequestTermination(self) 110 self.__lock.release()
111 112
113 - def _IsTerminationRequested(self):
114 """Returns true if termination has been requested. 115 116 return -- True if Terminate has been called.""" 117 118 self.__lock.acquire() 119 terminated = ExecutionEngine._IsTerminationRequested(self) 120 self.__lock.release() 121 return terminated
122 123 124 ######################################################################## 125 # Local Variables: 126 # mode: python 127 # indent-tabs-mode: nil 128 # fill-column: 72 129 # End: 130

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.executable-module.html0000664000076400007640000001274211122067145024707 0ustar stefanstefan qm.executable
Package qm :: Module executable
[hide private]
[frames] | no frames]

Module executable

source code

Classes [hide private]
  Executable
An 'Executable' is a program that the operating system can run.
  TimeoutExecutable
A 'TimeoutExecutable' runs for a limited time.
  RedirectedExecutable
A 'RedirectedExecutable' redirects the standard I/O streams.
  Filter
A 'FilterExecutable' feeds an input string to another proces.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_Util-module.html0000664000076400007640000000720011122067144031737 0ustar stefanstefan DT_Util

Module DT_Util


Classes

Eval

Functions

careful_getattr
careful_getitem
careful_getslice
careful_hasattr
careful_pow
careful_range
html_quote
int_param
name_param
namespace
obsolete_attr
parse_params
render
test

Variables

Expr_doc
ParseError
ValidationError
d
expr_globals
name

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/crarr.png0000664000076400007640000000052411122067143021611 0ustar stefanstefanPNG  IHDR eE,tEXtCreation TimeTue 22 Aug 2006 00:43:10 -0500` XtIME)} pHYsnu>gAMA aEPLTEðf4sW ЊrD`@bCܖX{`,lNo@xdE螊dƴ~TwvtRNS@fMIDATxc`@0&+(;; /EXؑ? n  b;'+Y#(r<"IENDB`qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_stream-module.html0000664000076400007640000001203311122067145030161 0ustar stefanstefan qm.test.classes.dejagnu_stream
Package qm :: Package test :: Package classes :: Module dejagnu_stream
[hide private]
[frames] | no frames]

Module dejagnu_stream

source code

Classes [hide private]
  DejaGNUStream
A 'DejaGNUStream' formats its output like DejaGNU.
  DejaGNUReader
A 'DejaGNUReader' reads a DejaGNU log file.
qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-H.html0000664000076400007640000006120511122067144024300 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

H



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.suite.Suite-class.html0000664000076400007640000005505311122067150025603 0ustar stefanstefan qm.test.suite.Suite
qm :: test :: suite :: Suite :: Class Suite
[hide private]
[frames] | no frames]

Class Suite

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     Suite
Known Subclasses:

A collection of tests.

 A test suite is a collection of tests.  The suite may contain other
suites by reference as well; all tests contained in these contained
suites are considered contained in the containing suite as well.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Runnable'.
source code
 
GetDatabase(self)
Return the 'Database' that contains this suite.
source code
 
GetId(self)
Return the ID of this test suite.
source code
 
GetTestIds(self)
Return the tests contained in this suite.
source code
 
GetSuiteIds(self)
Return the suites contained in this suite.
source code
 
IsImplicit(self)
Return true if this is an implicit test suite.
source code
 
GetAllTestAndSuiteIds(self)
Return the tests/suites contained in this suite and its subsuites.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = []
A list of the arguments to the extension class.
  kind = 'suite'
A string giving kind of extension is implemented by the class.
  EXTRA_ID = 'qmtest_id'
The name of the extra keyword argument to '__init__' that specifies the name of the test or resource.
  EXTRA_DATABASE = 'qmtest_database'
The name of the extra keyword argument to '__init__' that specifies the database containing the test or resource.
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Runnable'.

'arguments' -- As for 'Extension.__init__'.

'args' -- As for 'Extension.__init__'.

Overrides: object.__init__

GetDatabase(self)

source code 

Return the 'Database' that contains this suite.

returns -- The 'Database' that contains this suite.

GetTestIds(self)

source code 

Return the tests contained in this suite.

returns -- A sequence of labels corresponding to the tests contained in this suite. Tests that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

GetSuiteIds(self)

source code 

Return the suites contained in this suite.

returns -- A sequence of labels corresponding to the suites contained in this suite. Suites that are contained in this suite only because they are contained in a suite which is itself contained in this suite are not returned.

IsImplicit(self)

source code 

Return true if this is an implicit test suite.

Implicit test suites cannot be edited.

GetAllTestAndSuiteIds(self)

source code 

Return the tests/suites contained in this suite and its subsuites.

returns -- A pair '(test_ids, suite_ids)'. The 'test_ids' and 'suite_ids' elements are both sequences of labels. The values returned include all tests and suites that are contained in this suite and its subsuites, recursively.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_If.Unless-class.html0000664000076400007640000001550011122067146031671 0ustar stefanstefan qm.external.DocumentTemplate.DT_If.Unless
Package qm :: Package external :: Package DocumentTemplate :: Module DT_If :: Class Unless
[hide private]
[frames] | no frames]

Class Unless

source code

Known Subclasses:

Instance Methods [hide private]
 
__init__(self, blocks) source code
Class Variables [hide private]
  name = 'unless'
  blockContinuations = ()
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.text_result_stream-module.html0000664000076400007640000000217411122067144031715 0ustar stefanstefan text_result_stream

Module text_result_stream


Classes

TextResultStream

[hide private] ././@LongLink0000000000000000000000000000015100000000000011562 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.pDocumentTemplate-module.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.pDocumentTemplate-module.0000664000076400007640000000430511122067144033203 0ustar stefanstefan pDocumentTemplate

Module pDocumentTemplate


Classes

DictInstance
InstanceDict
MultiMapping
TemplateDict

Functions

isFunctionType
isSimpleType
render_blocks

Variables

n
name

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.file-module.html0000664000076400007640000000230611122067144026674 0ustar stefanstefan file

Module file


Classes

FileContentsTest
SubstitutionField

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.common-module.html0000664000076400007640000001101611122067144024631 0ustar stefanstefan common

Module common


Classes

PythonException
QMException
RcConfiguration
UserError

Functions

close_file_on_exec
convert_from_dos_text
copy
format_exception
format_time
format_time_iso
format_traceback
get_doc_directory
get_lib_directory
get_share_directory
get_userid
get_username
html_to_text
load_class
load_module
make_unique_tag
open_temporary_file
open_temporary_file_fd
parse_assignment
parse_boolean
parse_string_list
parse_time
parse_time_iso
read_assignments
split_argument_list
split_path_fully
wrap_lines

Variables

program_name
rc

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.result_reader.ResultReader-class.html0000664000076400007640000004010111122067150030606 0ustar stefanstefan qm.test.result_reader.ResultReader
Package qm :: Package test :: Module result_reader :: Class ResultReader
[hide private]
[frames] | no frames]

Class ResultReader

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     ResultReader
Known Subclasses:

A 'ResultReader' provides access to stored test results.

For instance, a 'ResultReader' may load 'Result's from a pickle file or an XML file.

This is an abstract class.

See also 'ResultStream'.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments, **args)
Construct a new 'Extension'.
source code
 
GetAnnotations(self)
Return this run's dictionary of annotations.
source code
 
GetResult(self)
Return the next 'Result' from this reader.
source code
 
__iter__(self)
A 'ResultReader' can be iterated over.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  kind = 'result_reader'
A string giving kind of extension is implemented by the class.

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

GetResult(self)

source code 

Return the next 'Result' from this reader.

returns -- A 'Result', or 'None' if there are no more results.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.python.BaseExceptionTest-class.html0000664000076400007640000005153711122067147031740 0ustar stefanstefan qm.test.classes.python.BaseExceptionTest
Package qm :: Package test :: Package classes :: Module python :: Class BaseExceptionTest
[hide private]
[frames] | no frames]

Class BaseExceptionTest

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
                  test.Test --+
                              |
                             BaseExceptionTest

Base class for tests of exceptions.

Nested Classes [hide private]

Inherited from test.Test: OutcomeField, TestField

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, context, result)
Run the test.
source code
 
CheckArgument(self, exc_info, result)
Check that the exception argument matches expectations.
source code
 
MakeResult(self, exc_info, result)
Check the exception in 'exc_info' and construct the result.
source code

Inherited from test.Test: GetTargetGroup

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.TextField(name= "source", title= "Pytho...
A list of the arguments to the extension class.

Inherited from test.Test: PREREQUISITES_FIELD_ID, kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, context, result)

source code 

Run the test.

'context' -- A 'Context' giving run-time parameters to the test.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

Overrides: test.Test.Run
(inherited documentation)

CheckArgument(self, exc_info, result)

source code 

Check that the exception argument matches expectations.

'result' -- The result object for this test.

MakeResult(self, exc_info, result)

source code 

Check the exception in 'exc_info' and construct the result.

'result' -- The result object for this test.


Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.TextField(name= "source", title= "Python Source Code", desc\
ription= """The source code.

            This code may contain class definitions, function
            definitions, statements, and so forth.""", verbatim= "true\
", multiline= "true", default_value= "pass"), qm.fields.TextField(name\
= "exception_argument", title= "Exception Argument", description= """T\
he expected value of the exception.
...

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_expectation_database-module.html0000664000076400007640000001145211122067145032224 0ustar stefanstefan qm.test.classes.xml_expectation_database
Package qm :: Package test :: Package classes :: Module xml_expectation_database
[hide private]
[frames] | no frames]

Module xml_expectation_database

source code

Classes [hide private]
  XMLExpectationDatabase
An 'XMLExpectationDatabase' reads expectations from an XML file.
qmtest-2.4.1/share/doc/qmtest/html/manual/string._TemplateMetaclass-class.html0000664000076400007640000003002211122067151027032 0ustar stefanstefan string._TemplateMetaclass
string :: _TemplateMetaclass :: Class _TemplateMetaclass
[hide private]
[frames] | no frames]

Type _TemplateMetaclass

source code

object --+    
         |    
      type --+
             |
            _TemplateMetaclass

Instance Methods [hide private]
 
__init__(cls, name, bases, dct)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code

Inherited from type: __call__, __cmp__, __delattr__, __getattribute__, __hash__, __new__, __repr__, __setattr__, __subclasses__, mro

Inherited from object: __reduce__, __reduce_ex__, __str__

Class Variables [hide private]
  pattern = '\n %(delim)s(?:\n (?P<escaped>%(delim)s) | ...
Properties [hide private]

Inherited from type: __base__, __bases__, __basicsize__, __dictoffset__, __flags__, __itemsize__, __mro__, __name__, __weakrefoffset__

Inherited from object: __class__

Method Details [hide private]

__init__(cls, name, bases, dct)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Overrides: object.__init__
(inherited documentation)

Class Variable Details [hide private]

pattern

Value:
'''
    %(delim)s(?:
      (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
      (?P<named>%(id)s)      |   # delimiter and a Python identifier
      {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
      (?P<invalid>)              # Other ill-formed delimiter exprs
    )
    '''

././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_HTML.HTMLDefault-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_HTML.HTMLDefault-class.htm0000664000076400007640000004567411122067146032542 0ustar stefanstefan qm.external.DocumentTemplate.DT_HTML.HTMLDefault
Package qm :: Package external :: Package DocumentTemplate :: Module DT_HTML :: Class HTMLDefault
[hide private]
[frames] | no frames]

Class HTMLDefault

source code

DT_String.String --+    
                   |    
                HTML --+
                       |
                      HTMLDefault

HTML document templates that edit themselves through copy.

This is to make a distinction from HTML objects that should edit themselves in place.

Nested Classes [hide private]
  copy_class
HTML Document Templates
Instance Methods [hide private]
 
manage_edit(self, data, PARENTS, URL1, REQUEST)
edit a template
source code

Inherited from HTML: SubTemplate, __str__, errQuote, manage, manage_editDocument, manage_editForm, management_interface, parseTag, quotedHTML, tagre, varExtra

Inherited from DT_String.String: ZDocumentTemplate_afterRender, ZDocumentTemplate_beforeRender, __call__, __getstate__, __init__, cook, default, id, initvars, munge, name, parse, parse_block, parse_close, parse_error, read, read_raw, setName, skip_eol, var

Inherited from DT_String.String (private): _parseTag

Class Variables [hide private]
  copy_class__roles__ = ()
  manage_edit__roles__ = ()

Inherited from HTML: SubTemplate__roles__, errQuote__roles__, manage__roles__, manage_editDocument__roles__, manage_editForm__roles__, management_interface__roles__, parseTag__roles__, quotedHTML__roles__, tagre__roles__, varExtra__roles__

Inherited from DT_String.String: ZDocumentTemplate_afterRender__roles__, ZDocumentTemplate_beforeRender__roles__, _parseTag__roles__, commands, commands__roles__, cook__roles__, default__roles__, func_code, func_defaults, func_defaults__roles__, initvars__roles__, isDocTemp, munge__roles__, parse__roles__, parse_block__roles__, parse_close__roles__, parse_error__roles__, read__roles__, read_raw__roles__, setName__roles__, shared_globals, shared_globals__roles__, skip_eol__roles__, validate, validate__roles__, var__roles__

Method Details [hide private]

manage_edit(self, data, PARENTS, URL1, REQUEST)

source code 

edit a template

Overrides: DT_String.String.manage_edit

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.ShowSuitePage-class.html0000664000076400007640000004127611122067151027444 0ustar stefanstefan qm.test.web.web.ShowSuitePage
Package qm :: Package test :: Package web :: Module web :: Class ShowSuitePage
[hide private]
[frames] | no frames]

Class ShowSuitePage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      ShowSuitePage

Page for displaying the contents of a test suite.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server, suite, edit, is_new_suite)
Construct a new DTML context.
source code
 
MakeEditUrl(self)
Return the URL for editing this suite.
source code
 
MakeRunUrl(self)
Return the URL for running this suite.
source code
 
MakeDeleteScript(self)
Make a script to confirm deletion of the suite.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server, suite, edit, is_new_suite)
(Constructor)

source code 

Construct a new DTML context.

'server' -- The 'QMTestServer' creating this page.

'suite' -- The 'Suite' instance to display.

'edit' -- If true, display controls for editing the suite.

'is_new_suite' -- If true, the suite being displayed is being created at this time.

Overrides: web.DtmlPage.__init__

MakeDeleteScript(self)

source code 

Make a script to confirm deletion of the suite.

returns -- JavaScript source for a function, 'delete_script', which shows a popup confirmation window.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_database-module.html0000664000076400007640000001204211122067145027615 0ustar stefanstefan qm.test.classes.xml_database
Package qm :: Package test :: Package classes :: Module xml_database
[hide private]
[frames] | no frames]

Module xml_database

source code

Classes [hide private]
  TestFileError
An error in the format or contents of an XML test file.
  XMLDatabase
A database representing tests as XML files in a directory tree.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler_test.CompilerBase-class.html0000664000076400007640000003132211122067147032232 0ustar stefanstefan qm.test.classes.compiler_test.CompilerBase
Package qm :: Package test :: Package classes :: Module compiler_test :: Class CompilerBase
[hide private]
[frames] | no frames]

Class CompilerBase

source code

A 'CompilerBase' is used by compilation test and resource clases.

Instance Methods [hide private]
 
_GetDirectory(self, context)
Get the name of the directory in which to run.
source code
 
_MakeDirectory(self, context)
Create a directory in which to place generated files.
source code
 
_RemoveDirectory(self, context, result)
Remove the directory in which generated files are placed.
source code
 
_GetObjectFileName(self, source_file_name, object_extension)
Return the default object file name for 'source_file_name'.
source code
Method Details [hide private]

_GetDirectory(self, context)

source code 

Get the name of the directory in which to run.

'context' -- A 'Context' giving run-time parameters to the test.

'returns' -- The name of the directory in which this test or resource will execute.

_MakeDirectory(self, context)

source code 

Create a directory in which to place generated files.

'context' -- A 'Context' giving run-time parameters to the test.

returns -- The name of the directory.

_RemoveDirectory(self, context, result)

source code 

Remove the directory in which generated files are placed.

'result' -- The 'Result' of the test or resource. If the 'result' indicates success, the directory is removed. Otherwise, the directory is left behind to allow investigation of the reasons behind the test failure.

_GetObjectFileName(self, source_file_name, object_extension)

source code 

Return the default object file name for 'source_file_name'.

'source_file_name' -- A string giving the name of a source file.

'object_extension' -- The extension used for object files.

returns -- The name of the object file that will be created by compiling 'source_file_name'.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.pickle_result_stream-module.html0000664000076400007640000001552511122067145031422 0ustar stefanstefan qm.test.classes.pickle_result_stream
Package qm :: Package test :: Package classes :: Module pickle_result_stream
[hide private]
[frames] | no frames]

Module pickle_result_stream

source code

Classes [hide private]
  PickleResultStream
A 'PickleResultStream' writes out results as Python pickles.
  PickleResultReader
A 'PickleResultReader' reads in results from pickle files.
Variables [hide private]
  _annotation_sentinel = None
The sentinel value that marks the beginning of an annotation.
  _int_format = '!I'
  _int_size = 4
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.runnable.Runnable-class.html0000664000076400007640000005712611122067150026740 0ustar stefanstefan qm.test.runnable.Runnable
qm :: test :: runnable :: Runnable :: Class Runnable
[hide private]
[frames] | no frames]

Class Runnable

source code

         object --+    
                  |    
extension.Extension --+
                      |
                     Runnable
Known Subclasses:

A 'Runnable' can run on a 'Target'.

'Runnable' is an abstract base class for 'Test' and 'Resource'.

Nested Classes [hide private]
  ResourceField
A 'ResourceField' contains the name of a resource.

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Runnable'.
source code
 
GetId(self)
Return the name of this test or resource.
source code
 
GetDatabase(self)
Return the 'Database' in which this test or resource is stored.
source code
 
GetAttachments(self)
Return the 'Attachment's to this 'Runnable'.
source code
 
__GetAttachments(self, field, value, attachments)
Return the 'Attachments' that are part of 'field'.
source code

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  EXTRA_ID = 'qmtest_id'
The name of the extra keyword argument to '__init__' that specifies the name of the test or resource.
  EXTRA_DATABASE = 'qmtest_database'
The name of the extra keyword argument to '__init__' that specifies the database containing the test or resource.
  RESOURCE_FIELD_ID = 'resources'
The name of the field that contains the resources on which this test or resource depends.
  arguments = [<<class 'qm.fields.SetField'> resources>]
A list of the arguments to the extension class.
  _argument_dictionary = {'resources': <<class 'qm.fields.SetFie...
A map from argument names to 'Field' instances.
  _argument_list = [<<class 'qm.fields.SetField'> resources>]
A list of all the 'Field's in this class.
  resources = []

Inherited from extension.Extension: kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Runnable'.

'arguments' -- As for 'Extension.__init__'.

'args' -- As for 'Extension.__init__.

Overrides: object.__init__

GetId(self)

source code 

Return the name of this test or resource.

'context' -- The 'Context' in which this entity is running.

returns -- The name of this test or resource.

GetDatabase(self)

source code 

Return the 'Database' in which this test or resource is stored.

returns -- The 'Database' in which this test or resource is stored.

GetAttachments(self)

source code 

Return the 'Attachment's to this 'Runnable'.

returns -- A sequence consisting of the 'Attachment' objects associated with this runnable.

__GetAttachments(self, field, value, attachments)

source code 

Return the 'Attachments' that are part of 'field'.

'field' -- The 'Field' being examined.

'value' -- The value of that 'Field' in 'self'.

'attachments' -- A sequence consisting of the attachments found so far. Additional 'Attachment's are appended to this sequence by this function.


Class Variable Details [hide private]

_argument_dictionary

A map from argument names to 'Field' instances.

A map from the names of arguments for this class to the corresponding 'Field'.

Value:
{'resources': <<class 'qm.fields.SetField'> resources>}

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test_database-module.html0000664000076400007640000001250611122067145032377 0ustar stefanstefan qm.test.classes.compilation_test_database
Package qm :: Package test :: Package classes :: Module compilation_test_database
[hide private]
[frames] | no frames]

Module compilation_test_database

source code

Classes [hide private]
  CompilationTest
A CompilationTest fetches compilation parameters from environment variables CPPFLAGS, <lang>_options, and <lang>_ldflags in addition to the CompilerTable-related parameters.
  CompilationTestDatabase
A 'CompilationTestDatabase' test database maps source code files to compilation tests.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_engine.TerminationRequested-class.html0000664000076400007640000001571411122067150033064 0ustar stefanstefan qm.test.execution_engine.TerminationRequested
Package qm :: Package test :: Module execution_engine :: Class TerminationRequested
[hide private]
[frames] | no frames]

Class TerminationRequested

source code

              object --+            
                       |            
exceptions.BaseException --+        
                           |        
        exceptions.Exception --+    
                               |    
              common.QMException --+
                                   |
                                  TerminationRequested

A target requested termination of the test loop.

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc.html0000664000076400007640000006362311122067144021457 0ustar stefanstefan Table of Contents

Table of Contents


Everything

Modules

math
qm
qm.attachment
qm.cmdline
qm.common
qm.config
qm.db
qm.diagnostic
qm.dist
qm.dist.command
qm.dist.command.build_extensions
qm.dist.command.install_extensions
qm.dist.distribution
qm.executable
qm.extension
qm.external
qm.external.DocumentTemplate
qm.external.DocumentTemplate.DT_HTML
qm.external.DocumentTemplate.DT_If
qm.external.DocumentTemplate.DT_In
qm.external.DocumentTemplate.DT_InSV
qm.external.DocumentTemplate.DT_Let
qm.external.DocumentTemplate.DT_Raise
qm.external.DocumentTemplate.DT_Return
qm.external.DocumentTemplate.DT_String
qm.external.DocumentTemplate.DT_Try
qm.external.DocumentTemplate.DT_UI
qm.external.DocumentTemplate.DT_Util
qm.external.DocumentTemplate.DT_Var
qm.external.DocumentTemplate.DT_With
qm.external.DocumentTemplate.DTtestExpr
qm.external.DocumentTemplate.DocumentTemplate
qm.external.DocumentTemplate.VSEval
qm.external.DocumentTemplate.gparse
qm.external.DocumentTemplate.pDocumentTemplate
qm.external.DocumentTemplate.setup
qm.fields
qm.host
qm.label
qm.lock
qm.platform
qm.platform_unix
qm.platform_win32
qm.queue
qm.setup
qm.structured_text
qm.temporary_directory
qm.test
qm.test.base
qm.test.classes
qm.test.classes.command
qm.test.classes.command_host
qm.test.classes.compilation_test
qm.test.classes.compilation_test_database
qm.test.classes.compiler
qm.test.classes.compiler_table
qm.test.classes.compiler_test
qm.test.classes.dejagnu_base
qm.test.classes.dejagnu_stream
qm.test.classes.dejagnu_test
qm.test.classes.dg_test
qm.test.classes.dir_run_database
qm.test.classes.explicit_suite
qm.test.classes.file
qm.test.classes.file_label
qm.test.classes.local_host
qm.test.classes.mount_database
qm.test.classes.pickle_result_stream
qm.test.classes.previous_testrun
qm.test.classes.process_target
qm.test.classes.python
qm.test.classes.python_label
qm.test.classes.rsh_target
qm.test.classes.serial_target
qm.test.classes.simulator
qm.test.classes.sql_result_stream
qm.test.classes.ssh_host
qm.test.classes.temporary
qm.test.classes.tet_stream
qm.test.classes.text_result_stream
qm.test.classes.thread_target
qm.test.classes.xml_database
qm.test.classes.xml_expectation_database
qm.test.classes.xml_result_stream
qm.test.cmdline
qm.test.command_thread
qm.test.context
qm.test.database
qm.test.directory_suite
qm.test.execution_engine
qm.test.execution_thread
qm.test.expectation_database
qm.test.file_database
qm.test.file_result_reader
qm.test.file_result_stream
qm.test.parameter_database
qm.test.reader_test_run
qm.test.report
qm.test.resource
qm.test.resource_adapter
qm.test.result
qm.test.result_reader
qm.test.result_stream
qm.test.run_database
qm.test.runnable
qm.test.suite
qm.test.target
qm.test.test
qm.test.test_run
qm.test.web
qm.test.web.web
qm.trace
qm.user
qm.web
qm.xmlutil
random
string

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.target-module.html0000664000076400007640000001103211122067145025021 0ustar stefanstefan qm.test.target
Package qm :: Package test :: Module target
[hide private]
[frames] | no frames]

Module target

source code

Classes [hide private]
  Target
Base class for target implementations.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.process_target-module.html0000664000076400007640000000215211122067144031000 0ustar stefanstefan process_target

Module process_target


Classes

ProcessTarget

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields-module.html0000664000076400007640000002234011122067145024027 0ustar stefanstefan qm.fields
Package qm :: Module fields
[hide private]
[frames] | no frames]

Module fields

source code

A 'Field' determines how data is displayed and stored.

A 'Field' is a component of a data structure. Every 'Field' has a type. For example, an 'IntegerField' stores a signed integer while a 'TextField' stores a string.

The value of a 'Field' can be represented as HTML (for display in the GUI), or as XML (when written to persistent storage). Every 'Field' can create an HTML form that can be used by the user to update the value of the 'Field'.

Every 'Extension' class has a set of arguments composed of 'Field'. An instance of that 'Extension' class can be constructed by providing a value for each 'Field' object. The GUI can display the 'Extension' object by rendering each of the 'Field' values as HTML. The user can change the value of a 'Field' in the GUI, and then write the 'Extension' object to persistent storage.

Additional derived classes of 'Field' can be created for use in domain-specific situations. For example, the QMTest 'Test' class defines a derived class which allows the user to select from among a set of test names.

Classes [hide private]
  Field
A 'Field' is a named, typed component of a data structure.
  IntegerField
An 'IntegerField' stores an 'int' or 'long' object.
  TextField
A field that contains text.
  TupleField
A 'TupleField' contains zero or more other 'Field' objects.
  DictionaryField
A 'DictionaryField' maps keys to values.
  SetField
A field containing zero or more instances of some other field.
  UploadAttachmentPage
DTML context for generating upload-attachment.dtml.
  AttachmentField
A field containing a file attachment.
  ChoiceField
A 'ChoiceField' allows choosing one of several values.
  EnumerationField
A field that contains an enumeral value.
  BooleanField
A field containing a boolean value.
  TimeField
A field containing a date and time.
  PythonField
A 'PythonField' stores a Python value.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.ssh_host.SSHHost-class.html0000664000076400007640000010270011122067147030140 0ustar stefanstefan qm.test.classes.ssh_host.SSHHost
Package qm :: Package test :: Package classes :: Module ssh_host :: Class SSHHost
[hide private]
[frames] | no frames]

Class SSHHost

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
              host.Host --+
                          |
                         SSHHost

An 'SSHHost' is accessible via 'ssh' or a similar program.

Nested Classes [hide private]

Inherited from host.Host: Executable

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, path, arguments, environment=None, timeout=-1, relative=False)
Run a program on the remote host.
source code
 
UploadFile(self, local_file, remote_file=None)
Copy 'local_file' to 'remote_file'.
source code
 
DownloadFile(self, remote_file, local_file=None)
Copy 'remote_file' to 'local_file'.
source code
 
DeleteFile(self, remote_file)
Delete the 'remote_file'.
source code
 
_FormSSHCommandLine(self, path, arguments, environment=None)
Form the 'ssh' command line.
source code
 
_FormSCPCommandLine(self, upload, local_file, remote_file)
Form the 'scp' command line.
source code

Inherited from host.Host: UploadAndRun, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  host_name = TextField()
  ssh_program = TextField(default_value= "ssh", description= """...
  ssh_args = SetField(TextField(description= """The arguments to...
  scp_program = TextField(default_value= "scp", description= """...
  scp_args = SetField(TextField(description= """The arguments to...
  default_dir = TextField(description= """The default directory ...
  nfs_dir = TextField(description= """The default directory, as ...
  user_name = TextField(description= """The user name on the rem...

Inherited from host.Host: kind

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, path, arguments, environment=None, timeout=-1, relative=False)

source code 

Run a program on the remote host.

'path' -- The name of the program to run, on the remote host. If 'relative' is true, or if 'path' is not an absolute path but does contain at least one directory separator, then 'path' is interpreted relative to the default directory. Otherwise, 'path' is used unmodified.

'arguments' -- The sequence of arguments that should be passed to the program.

'environment' -- If not 'None', a dictionary of pairs of strings to add to the environment of the running program.

'timeout' -- The number of seconds the program is permitted to execute. After the 'timeout' expires, the program will be terminated. However, in some cases (such as when using 'rsh') it will be the local side of the connection that is closed. The remote side of the connection may or may not continue to operate, depending on the vagaries of the remote operating system.

returns -- A pair '(status, output)'. The 'status' is the exit status returned by the program, or 'None' if the exit status is not available. The 'output' is a string giving the combined standard output and standard error output from the program.

Overrides: host.Host.Run
(inherited documentation)

UploadFile(self, local_file, remote_file=None)

source code 

Copy 'local_file' to 'remote_file'.

'local_file' -- The name of the file on the local machine.

'remote_file' -- The name of the file on the remote machine. The 'remote_file' must be a relative path. It is interpreted relative to the default directory. If 'None', the 'remote_file' is placed in the default directory using the basename of the 'local_file'.

If the 'local_file' and 'remote_file' are the same, then this function succeeds, but takes no action.

Overrides: host.Host.UploadFile
(inherited documentation)

DownloadFile(self, remote_file, local_file=None)

source code 

Copy 'remote_file' to 'local_file'.

'remote_file' -- The name of the file on the remote machine. The 'remote_file' must be a relative path. It is interpreted relative to the default directory.

'local_file' -- The name of the file on the local machine. If 'None', the 'local_file' is placed in the current directory using the basename of the 'remote_file'.

If the 'local_file' and 'remote_file' are the same, then this function succeeds, but takes no action.

Overrides: host.Host.DownloadFile
(inherited documentation)

DeleteFile(self, remote_file)

source code 

Delete the 'remote_file'.

'remote_file' -- A relative path to the file to be deleted.

Overrides: host.Host.DeleteFile
(inherited documentation)

_FormSSHCommandLine(self, path, arguments, environment=None)

source code 

Form the 'ssh' command line.

'path' -- The remote command, in the same format expected by 'Run'.

'arguments' -- The arguments to the remote command.

'environment' -- As for 'Run'.

returns -- A pair '(path, arguments)' describing the command to run on the local machine that will execute the remote command.

_FormSCPCommandLine(self, upload, local_file, remote_file)

source code 

Form the 'scp' command line.

'upload' -- True iff the 'local_file' should be copied to the remote host.

'local_file' -- The path to the local file.

'remote_file' -- The path to the remote file.

returns -- The list of arguments for a command to run on the local machine that will perform the file copy.


Class Variable Details [hide private]

ssh_program

Value:
TextField(default_value= "ssh", description= """The path to the remote\
 shell program.""")

ssh_args

Value:
SetField(TextField(description= """The arguments to the remote shell p\
rogram."""))

scp_program

Value:
TextField(default_value= "scp", description= """The path to the remote\
 copy program.""")

scp_args

Value:
SetField(TextField(description= """The arguments to the remote copy pr\
ogram."""))

default_dir

Value:
TextField(description= """The default directory on the remote system."\
"")

nfs_dir

Value:
TextField(description= """The default directory, as seen from the loca\
l host.
    
        If not empty, 'nfs_dir' is a directory on the local machine
        that is equivalent to the default directory on the remote
        machine.  In that case, files will be copied to and from this
        directory on the local machine, rather than by using
        'scp'.""")

user_name

Value:
TextField(description= """The user name on the remote host.

        If not empty, the user name that should be used when
        connecting to the remote host.""")

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-random-module.html0000664000076400007640000000776011122067145024221 0ustar stefanstefan random

Module random


Classes

Random
SystemRandom
WichmannHill

Functions

_test
_test_generator
betavariate
choice
expovariate
gammavariate
gauss
getrandbits
getstate
jumpahead
lognormvariate
normalvariate
paretovariate
randint
random
randrange
sample
seed
setstate
shuffle
uniform
vonmisesvariate
weibullvariate

Variables

BPF
LOG4
NV_MAGICCONST
RECIP_BPF
SG_MAGICCONST
TWOPI
_e
_inst
_pi

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-J.html0000664000076400007640000001324711122067144024305 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

J



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.lock-pysrc.html0000664000076400007640000002574611122067162023400 0ustar stefanstefan qm.lock
Package qm :: Module lock
[hide private]
[frames] | no frames]

Source Code for Module qm.lock

 1  ######################################################################## 
 2  # 
 3  # File:   lock.py 
 4  # Author: Mark Mitchell 
 5  # Date:   07/03/2002 
 6  # 
 7  # Contents: 
 8  #   Lock 
 9  # 
10  # Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Notes 
18  ######################################################################## 
19   
20  # On systems that do not support threads, Threading.Lock() is 
21  # unavailable.  This module provides a class with the same interface 
22  # that works on systems without threads. 
23   
24  try: 
25      import thread 
26      from threading import Lock, RLock 
27  except: 
28   
29 - class Lock:
30
31 - def acquire(blocking = 1):
32 # The lock can always be acquired. 33 pass
34
35 - def release():
36 # There is nothing to do to release the lock. 37 pass
38 39 40
41 - class RLock(Lock):
42 43 pass
44

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.database.NoSuchSuiteError-class.html0000664000076400007640000002265211122067150030347 0ustar stefanstefan qm.test.database.NoSuchSuiteError
qm :: test :: database :: NoSuchSuiteError :: Class NoSuchSuiteError
[hide private]
[frames] | no frames]

Class NoSuchSuiteError

source code

              object --+                    
                       |                    
exceptions.BaseException --+                
                           |                
        exceptions.Exception --+            
                               |            
              common.QMException --+        
                                   |        
                       DatabaseError --+    
                                       |    
                         NoSuchItemError --+
                                           |
                                          NoSuchSuiteError

The specified suite does not exist.

Instance Methods [hide private]
 
__init__(self, suite_id)
Construct a new 'NoSuchSuiteError'
source code

Inherited from NoSuchItemError: __str__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, suite_id)
(Constructor)

source code 

Construct a new 'NoSuchSuiteError'

'suite_id' -- The name of the suite that does not exist.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes-module.html0000664000076400007640000002215111122067145025174 0ustar stefanstefan qm.test.classes
Package qm :: Package test :: Package classes
[hide private]
[frames] | no frames]

Package classes

source code

Submodules [hide private]

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test-module.html0000664000076400007640000003054511122067145023546 0ustar stefanstefan qm.test
Package qm :: Package test
[hide private]
[frames] | no frames]

Package test

source code

Submodules [hide private]

././@LongLink0000000000000000000000000000014600000000000011566 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_String.FileMixin-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_String.FileMixin-class.htm0000664000076400007640000002441311122067146033043 0ustar stefanstefan qm.external.DocumentTemplate.DT_String.FileMixin
Package qm :: Package external :: Package DocumentTemplate :: Module DT_String :: Class FileMixin
[hide private]
[frames] | no frames]

Class FileMixin

source code

Known Subclasses:

Instance Methods [hide private]
 
__init__(self, file_name='', mapping=None, __name__='', **vars)
Create a document template based on a named file.
source code
 
read_raw(self) source code
Class Variables [hide private]
  edited_source = ''
  read_raw__roles__ = ()
Method Details [hide private]

__init__(self, file_name='', mapping=None, __name__='', **vars)
(Constructor)

source code 

Create a document template based on a named file.

The optional parameter, 'mapping', may be used to provide a mapping object containing defaults for values to be inserted.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Raise.Raise-class.html0000664000076400007640000002060611122067146032173 0ustar stefanstefan qm.external.DocumentTemplate.DT_Raise.Raise
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Raise :: Class Raise
[hide private]
[frames] | no frames]

Class Raise

source code

Instance Methods [hide private]
 
__init__(self, blocks) source code
 
render(self, md) source code
 
__call__(self, md) source code
Class Variables [hide private]
  blockContinuations = ()
  name = 'raise'
  expr = ''
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.test_run-module.html0000664000076400007640000000210411122067144026160 0ustar stefanstefan test_run

Module test_run


Classes

TestRun

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_In-module.html0000664000076400007640000005020711122067145030613 0ustar stefanstefan qm.external.DocumentTemplate.DT_In
Package qm :: Package external :: Package DocumentTemplate :: Module DT_In
[hide private]
[frames] | no frames]

Module DT_In

source code

Sequence insertion

   A sequence may be inserted using an 'in' command.  The 'in'
   command specifies the name of a sequence object and text to
   be inserted for each element in the sequence.

   The EPFS syntax for the in command is::

      %(in name)[
           text
      %(in name)]

   The HTML syntax for the in command is::

      <!--#in name-->
           text
      <!--#/in name-->

  See the example below that shows how 'if', 'else', and 'in' commands
  may be combined to display a possibly empty list of objects.

  The text included within an 'in' command will be refered to
  as an 'in' block.

Synopsis

  If the variable 'sequence' exists as a sequence, a simple case
  of the 'in' tag is used as follows::

     <!--#in sequence-->some markup<!--#/in-->

  A more complete case is used as follows::

    <!--#in sequence sort=age-->
      <!--#var sequence-number-->) <!--#var age-->
    <!--#/in-->

Attributes

  sort -- Define the sort order for sequence items.  Parameter to the
  attribute is either a sort option, or list of sort options separated
  by comma.  Every sort option consists of variable name, optional
  comparison function name (default is cmp) and optional sort order
  (default is asc).
      Examples: sort="date" or sort="date,time" or
  sort="title/locale,date/cmp/desc". If you want to specify sort order,
  you cannot omit the function; use cmp for standard comparison.
      Few predefined comparison functions available: standard cmp,
  nocase (ignore string case), strcoll (alias "locale"),
  strcoll_nocase (alias "locale_nocase"). Locale functions are
  available only if module locale is already imported (you started Zope
  with -L locale).

  sort_expr -- The "sort" attribute accepts only static list of
  sort options. This calculated parameter allows you to calculate the
  list of sort options on the fly.

  sort_expr -- This allows an expression to control sort order.

  reverse -- Reverse the sequence (may be combined with sort).  Note
  that this can cause a huge memory use in lazy activation instances.

  reverse_expr -- This calculated parameter allows you to calculate the
  need of reversing on the fly.

  Within an 'in' block, variables are substituted from the
  elements of the iteration unless the 'no_push_item' optional
  is specified.  The elements may be either instance or mapping
  objects.  In addition, the variables:

     'sequence-item' -- The element.

     'sequence-var-nnn' -- The value of a specific named attribute
       of the item, where 'nnn' is the name.  For example, to get
       an items 'title' attribute, use 'sequence-var-title'.  This
       construct is most useful in an 'if' tag to test whether an
       attribute is present, because the attribute lookup will be
       extended to the full document template namespace.

     'sequence-key' -- The key associated with the element in an
       items list. See below.

     'sequence-index' -- The index, starting from 0, of the
       element within the sequence.

     'sequence-number' -- The index, starting from 1, of the
       element within the sequence.

     'sequence-letter' -- The index, starting from 'a', of the
       element within the sequence.

     'sequence-Letter' -- The index, starting from 'A', of the
       element within the sequence.

     'sequence-roman' -- The index, starting from 'i', of the
       element within the sequence.

     'sequence-Roman' -- The index, starting from 'I', of the
       element within the sequence.

     'sequence-start' -- A variable that is true if the element
       being displayed is the first of the displayed elements,
       and false otherwise.

     'sequence-end' -- A variable that is true if the element
       being displayed is the last of the displayed elements,
       and false otherwise.

  are defined for each element.

  Normally, 'in' blocks are used to iterate over sequences of
  instances.  If the optional parameter 'mapping' is specified
  after the sequence name, then the elements of the sequence
  will be treated as mapping objects.

  An 'in' command may be used to iterate over a sequence of
  dictionary items.  If the elements of the iteration are
  two-element tuples, then then the template code given in the
  'in' block will be applied to the second element of each
  tuple and may use a variable, 'sequence-key' to access the
  first element in each tuple.

Batch sequence insertion

  When displaying a large number of objects, it is sometimes
  desirable to display just a sub-sequence of the data.
  An 'in' command may have optional parameters,
  as in::

      <!--#in values start=start_var size=7-->

  The parameter values may be either integer literals or
  variable names.

  Up to five parameters may be set:

      'start'   -- The number of the first element to be shown,
                   where elements are numbered from 1.

      'end'     -- The number of the last element to be shown,
                   where elements are numbered from 1.

      'size'    -- The desired number of elements to be shown at
                   once.

      'orphan'  -- The desired minimum number of objects to be
                   displayed.  The default value for this
                   parameter is 3.

      'overlap' -- The desired overlap between batches. The
                   default is no overlap.

  Typically, only 'start' and 'size' will be specified.

  When batch insertion is used, several additional variables are
  defined for use within the sequence insertion text:

      'sequence-query' -- The original query string given in a get
         request with the form variable named in the 'start'
         attribute removed.  This is extremely useful when
         building URLs to fetch another batch.

         To see how this is used, consider the following example::

             <!--#in search_results size=20 start=batch_start-->

                ... display rows

                <!--#if sequence-end--> <!--#if next-sequence-->
                  <a href="<!--#var URL-->/<!--#var sequence-query
                      -->&batch_start=<!--#var
                      next-sequence-start-number-->">
                  (Next <!--#var next-sequence-size--> results)
                  </a>
                <!--#/if--> <!--#/if-->

             <!--#/in-->

         If the original URL is: 'foo/bar?x=1&y=2', then the
         rendered text (after row data are displayed) will be::

                  <a href="foo/bar?x=1&amp;y=2&amp;batch_start=20">
                  (Next 20 results)
                  </a>

         If the original URL is: 'foo/bar?batch_start=10&x=1&y=2',
         then the rendered text (after row data are displayed)
         will be::

                  <a href="foo/bar?x=1&amp;y=2&amp;batch_start=30">
                  (Next 20 results)
                  </a>

      'sequence-step-start-index' -- The index, starting from 0,
         of the start of the current batch.

      'sequence-step-end-index' -- The index, starting from 0, of
         the end of the current batch.

      'sequence-step-size' -- The batch size used.

      'previous-sequence' -- This variable will be true when the
         first element is displayed and when the first element
         displayed is not the first element in the sequence.

      'previous-sequence-start-index' -- The index, starting from
         0, of the start of the batch previous to the current
         batch.

      'previous-sequence-end-index' -- The index, starting from
         0, of the end of the batch previous to the current
         batch.

      'previous-sequence-size' -- The size of the batch previous to
         the current batch.

      'previous-batches' -- A sequence of mapping objects
         containing information about all of the batches prior
         to the batch being displayed.

         Each of these mapping objects include the following
         variables:

            batch-start-index -- The index, starting from
               0, of the beginning of the batch.

            batch-end-index -- The index, starting from
               0, of the end of the batch.

            batch-size -- The size of the batch.

      'next-sequence' -- This variable will be true when the last
         element is displayed and when the last element
         displayed is not the last element in the sequence.

      'next-sequence-start-index' -- The index, starting from
         0, of the start of the batch after the current
         batch.

      'next-sequence-end-index' -- The index, starting from
         0, of the end of the batch after the current
         batch.

      'next-sequence-size' -- The size of the batch after
         the current batch.

      'next-batches' -- A sequence of mapping objects
         containing information about all of the batches after
         the batch being displayed.

         Each of these mapping objects include the following
         variables:

            batch-start-index -- The index, starting from
               0, of the beginning of the batch.

            batch-end-index -- The index, starting from
               0, of the end of the batch.

            batch-size -- The size of the batch.

  For each of the variables listed above with names ending in
  "-index", there are variables with names ending in "-number",
  "-roman", "-Roman", "-letter", and "-Letter" that are indexed
  from 1, "i", "I", "a", and "A", respectively.  In addition,
  for every one of these variables there are variables with
  names ending in "-var-xxx", where "xxx" is an element
  attribute name or key.

Summary statistics

  When performing sequence insertion, special variables may be
  used to obtain summary statistics.  To obtain a summary
  statistic for a variable, use the variable name:
  'statistic-name', where 'statistic' is a statistic name and
  'name' is the name of a data variable.

  Currently supported statistic names are:

    total -- The total of numeric values.

    count -- The total number of non-missing values.

    min -- The minimum of non-missing values.

    max -- The maximum of non-missing values.

    median -- The median of non-missing values.

    mean -- The mean of numeric values values.

    variance -- The variance of numeric values computed with a
      degrees of freedom equal to the count - 1.

    variance-n -- The variance of numeric values computed with a
      degrees of freedom equal to the count.

    standard-deviation -- The standard deviation of numeric values
      computed with a degrees of freedom equal to the count - 1.

    standard-deviation-n -- The standard deviation of numeric
      values computed with a degrees of freedom equal to the count.

  Missing values are either 'None' or the attribute 'Value'
  of the module 'Missing', if present.

'else' continuation tag within in

  An 'else' tag may be used as a continuation tag in the 'in' tag.
  The source after the 'else' tag is inserted if:

    - The sequence given to the 'in' tag is of zero length, or

    - The 'previous' attribute was used and their are no
      previous batches, or

    - The 'next' attribute was used and their are no
      next batches, or


Version: 1069

Classes [hide private]
  InFactory
  InClass
Functions [hide private]
True if D has a key k, else False
basic_type(D, k) source code
 
int_param(params, md, name, default=0, st=<type 'str'>) source code
Variables [hide private]
  __rcs_id__ = '$Id: DT_In.py 1069 2008-11-13 21:55:43Z stefan $'
  In = InFactory()
././@LongLink0000000000000000000000000000015000000000000011561 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_HTML.dtml_re_class-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_HTML.dtml_re_class-class.h0000664000076400007640000001711011122067146032723 0ustar stefanstefan qm.external.DocumentTemplate.DT_HTML.dtml_re_class
Package qm :: Package external :: Package DocumentTemplate :: Module DT_HTML :: Class dtml_re_class
[hide private]
[frames] | no frames]

Class dtml_re_class

source code

This needs to be replaced before 2.4. It's a hackaround.

Instance Methods [hide private]
 
search(self, text, start=0, name_match=<built-in method match of _sre.SRE_Pattern object at 0x7f00bc6..., end_match=<built-in method match of _sre.SRE_Pattern object at 0x7f00bc7..., start_search=<built-in method search of _sre.SRE_Pattern object at 0x7f00bc..., ent_name=<built-in method match of _sre.SRE_Pattern object at 0x29d3a40>) source code
 
group(self, *args) source code
 
start(self, *args) source code
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.gparse-module.html0000664000076400007640000000346311122067144031723 0ustar stefanstefan gparse

Module gparse


Functions

compile
dot_munge
item_munge
multi_munge
munge
slice_munge

Variables

ParseError

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.xml_expectation_database-pysrc.html0000664000076400007640000015535511122067152032110 0ustar stefanstefan qm.test.classes.xml_expectation_database
Package qm :: Package test :: Package classes :: Module xml_expectation_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.xml_expectation_database

 1  ######################################################################## 
 2  # 
 3  # File:   xml_expectation_database.py 
 4  # Author: Stefan Seefeld 
 5  # Date:   2007-09-18 
 6  # 
 7  # Contents: 
 8  #   QMTest XMLExpectationDatabase extension class. 
 9  # 
10  # Copyright (c) 2007 by CodeSourcery, Inc.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from qm.fields import TextField 
21  from qm.test.expectation_database import ExpectationDatabase 
22  from qm.test.result import Result 
23  from qm.test.base import load_results 
24  from qm.xmlutil import * 
25  import re 
26   
27  ######################################################################## 
28  # Classes 
29  ######################################################################## 
30   
31 -class XMLExpectationDatabase(ExpectationDatabase):
32 """An 'XMLExpectationDatabase' reads expectations from 33 an XML file.""" 34 35 file_name = TextField() 36 37
38 - def __init__(self, **args):
39 40 super(XMLExpectationDatabase, self).__init__(**args) 41 self._expectations = [] 42 document = load_xml(open(self.file_name)) 43 root = document.documentElement 44 for e in root.getElementsByTagName('expectation'): 45 test_id = e.getAttribute('test_id') 46 outcome = {'pass':Result.PASS, 47 'fail':Result.FAIL,}[e.getAttribute('outcome')] 48 filters = {} 49 for a in e.getElementsByTagName('annotation'): 50 filters[a.getAttribute('name')] = a.getAttribute('value') 51 description = e.getElementsByTagName('description') 52 if description: description = get_dom_text(description[0]) 53 self._expectations.append((test_id, outcome, filters, description))
54 55
56 - def Lookup(self, test_id):
57 58 59 outcome, description = Result.PASS, '' 60 for rule_id, rule_outcome, rule_annotations, rule_description in self._expectations: 61 if re.match(rule_id, test_id): 62 match = True 63 for a in rule_annotations.iteritems(): 64 if (a[0] not in self.testrun_parameters or 65 not re.match(a[1], self.testrun_parameters[a[0]])): 66 match = False 67 if match: 68 outcome = rule_outcome 69 description = rule_description 70 return Result(Result.TEST, test_id, outcome, 71 annotations={'description':description})
72

qmtest-2.4.1/share/doc/qmtest/html/manual/random.SystemRandom-class.html0000664000076400007640000005244611122067151025700 0ustar stefanstefan random.SystemRandom
random :: SystemRandom :: Class SystemRandom
[hide private]
[frames] | no frames]

Class SystemRandom

source code

    object --+        
             |        
_random.Random --+    
                 |    
            Random --+
                     |
                    SystemRandom

Alternate random number generator using sources provided
by the operating system (such as /dev/urandom on Unix or
CryptGenRandom on Windows).

 Not available on all systems (see os.urandom() for details).

Instance Methods [hide private]
None
_notimplemented(self, *args, **kwds)
Method should not be called for a system random number generator.
source code
None
_stub(self, *args, **kwds)
Stub method.
source code
x
getrandbits(k)
Generates a long int with k random bits.
source code
None
getstate(self, *args, **kwds)
Method should not be called for a system random number generator.
source code
None
jumpahead(self, *args, **kwds)
Stub method.
source code
x in the interval [0, 1).
random(self)
Get the next random number in the range [0.0, 1.0).
source code
None
seed(self, *args, **kwds)
Stub method.
source code
None
setstate(self, *args, **kwds)
Method should not be called for a system random number generator.
source code

Inherited from Random: __getstate__, __init__, __reduce__, __setstate__, betavariate, choice, expovariate, gammavariate, gauss, lognormvariate, normalvariate, paretovariate, randint, randrange, sample, shuffle, uniform, vonmisesvariate, weibullvariate

Inherited from Random (private): _randbelow

Inherited from _random.Random: __getattribute__, __new__

Inherited from object: __delattr__, __hash__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from Random: VERSION

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

_stub(self, *args, **kwds)

source code 

Stub method. Not used for a system random number generator.

Returns: None

getrandbits(k)

source code 

Generates a long int with k random bits.

Returns: x
Overrides: _random.Random.getrandbits

getstate(self, *args, **kwds)

source code 

Method should not be called for a system random number generator.

Returns: None
Overrides: _random.Random.getstate

jumpahead(self, *args, **kwds)

source code 

Stub method. Not used for a system random number generator.

Returns: None
Overrides: _random.Random.jumpahead

random(self)

source code 

Get the next random number in the range [0.0, 1.0).

Returns: x in the interval [0, 1).
Overrides: _random.Random.random

seed(self, *args, **kwds)

source code 

Stub method. Not used for a system random number generator.

Returns: None
Overrides: _random.Random.seed

setstate(self, *args, **kwds)

source code 

Method should not be called for a system random number generator.

Returns: None
Overrides: _random.Random.setstate

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.cmdline.CommandError-class.html0000664000076400007640000001560611122067145026412 0ustar stefanstefan qm.cmdline.CommandError
Package qm :: Module cmdline :: Class CommandError
[hide private]
[frames] | no frames]

Class CommandError

source code

              object --+                
                       |                
exceptions.BaseException --+            
                           |            
        exceptions.Exception --+        
                               |        
              common.QMException --+    
                                   |    
                    common.UserError --+
                                       |
                                      CommandError

Instance Methods [hide private]

Inherited from common.QMException: __init__

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.pickle_result_stream-module.html0000664000076400007640000000341111122067144032173 0ustar stefanstefan pickle_result_stream

Module pickle_result_stream


Classes

PickleResultReader
PickleResultStream

Variables


[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web-module.html0000664000076400007640000020671711122067145023352 0ustar stefanstefan qm.web
Package qm :: Module web
[hide private]
[frames] | no frames]

Module web

source code

Common code for implementing web user interfaces.

Classes [hide private]
  AddressInUseError
  PrivilegedPortError
  NoSessionError
  InvalidSessionError
  DtmlPage
Base class for classes to generate web pages from DTML.
  HttpRedirect
Exception signalling an HTTP redirect response.
  WebRequestHandler
Handler for HTTP requests.
  HTTPServer
Workaround for problems in 'BaseHTTPServer.HTTPServer'.
  WebServer
A web server that serves ordinary files and dynamic content.
  WebRequest
An object representing a request from the web server.
  CGIWebRequest
A 'WebRequest' object initialized from the CGI environment.
  Session
A persistent user session.
Functions [hide private]
 
_create_session_id() source code
 
parse_url_query(url)
Parse a URL-encoded query.
source code
 
http_return_html(html_text, stream=sys.stdout)
Generate an HTTP response consisting of HTML text.
source code
 
http_return_exception(exc_info=None, stream=sys.stdout)
Generate an HTTP response for an exception.
source code
 
format_exception(exc_info)
Format an exception as HTML.
source code
 
escape(text)
Escape special characters in 'text' for formatting as HTML.
source code
 
__replacement_for_entity(match) source code
 
unescape(text)
Undo 'escape' by replacing entities with ordinary characters.
source code
 
format_structured_text(text)
Render 'text' as HTML.
source code
 
make_url(script_name, base_request=None, **fields)
Create a request and return a URL for it.
source code
 
make_button_for_request(title, request, css_class=None)
Generate HTML for a button.
source code
 
make_button_for_url(title, url, css_class=None)
Generate HTML for a button.
source code
 
get_session(request, session_id)
Retrieve the session corresponding to 'session_id'.
source code
 
__clean_up_expired_sessions()
Remove any sessions that are expired.
source code
 
handle_login(request, default_redirect_url='/')
Handle a login request.
source code
 
handle_logout(request, default_redirect_url='/')
Handle a logout request.
source code
 
generate_error_page(request, error_text)
Generate a page to indicate a user error.
source code
 
generate_login_form(redirect_request, message=None)
Show a form for user login.
source code
 
make_set_control(form_name, field_name, add_page, select_name=None, initial_elements=[], request=None, rows=6, width=200, window_width=480, window_height=240, ordered=0)
Construct a control for representing a set of items.
source code
 
encode_set_control_contents(values)
Encode 'values' for a set control.
source code
 
decode_set_control_contents(content_string)
Decode the contents of a set control.
source code
 
make_properties_control(form_name, field_name, properties, select_name=None)
Construct a control for representing a set of properties.
source code
 
encode_properties(properties)
Construct a URL-encoded representation of a set of properties.
source code
 
decode_properties(properties)
Decode a URL-encoded representation of a set of properties.
source code
 
make_javascript_string(text)
Return 'text' represented as a JavaScript string literal.
source code
 
make_help_link(help_text_tag, label='Help', **substitutions)
Make a link to pop up help text.
source code
 
make_help_link_html(help_text, label='Help')
Make a link to pop up help text.
source code
 
make_popup_page(message, buttons, title='')
Generate a popup dialog box page.
source code
 
make_choose_control(field_name, included_label, included_items, excluded_label, excluded_items, item_to_text=<type 'str'>, item_to_value=<type 'str'>, ordered=0)
Construct HTML controls for selecting a subset.
source code
 
make_button_for_popup(label, url, window_width=480, window_height=240)
Construct a button for displaying a popup page.
source code
 
format_color(red, green, blue)
Format an RGB color value for HTML.
source code
 
javascript_escape(text)
Equivalent to the JavaScript 'escape' built-in function.
source code
 
javascript_unescape(text)
Equivalent to the JavaScript 'unescape' built-in function.
source code
 
make_submit_button(title='OK')
Generate HTML for a button to submit the current form.
source code
Variables [hide private]
  session_id_field = 'session'
The name of the form field used to store the session ID.
  __entity_regex = re.compile(r'&(\w+);')
  sessions = {}
A mapping from session IDs to 'Session' instances.
  _counter = 0
A counter for generating somewhat-unique names.
  _page_cache_name = 'page-cache'
The URL prefix for the global page cache.
  _session_cache_name = 'session-cache'
The URL prefix for the session page cache.
Function Details [hide private]

parse_url_query(url)

source code 

Parse a URL-encoded query.

This function parses query strings encoded in URLs, such as '/script.cgi?key1=val1&key2=val2'. For this example, it would return '("/script.cgi", {"key1" : "val1", "key2" : "val2"})'

'url' -- The URL to parse.

returns -- A pair containing the the base script path and a mapping of query field names to values.

http_return_html(html_text, stream=sys.stdout)

source code 

Generate an HTTP response consisting of HTML text.

'html_text' -- The HTML souce text to return.

'stream' -- The stream to write the response, by default 'sys.stdout.'.

http_return_exception(exc_info=None, stream=sys.stdout)

source code 

Generate an HTTP response for an exception.

'exc_info' -- A three-element tuple containing exception info, of the form '(type, value, traceback)'. If 'None', use the exception currently being handled.

'stream' -- The stream to write the response, by default 'sys.stdout.'.

format_exception(exc_info)

source code 

Format an exception as HTML.

'exc_info' -- A three-element tuple containing exception info, of the form '(type, value, traceback)'.

returns -- A string containing a complete HTML file displaying the exception.

make_url(script_name, base_request=None, **fields)

source code 

Create a request and return a URL for it.

'script_name' -- The script name for the request.

'base_request' -- If not 'None', the base request for the generated request.

'fields' -- Additional fields to include in the request.

make_button_for_request(title, request, css_class=None)

source code 

Generate HTML for a button.

Note that the caller is responsible for making sure the resulting button is placed within a form element.

'title' -- The button label.

'request' -- A 'WebRequest' object to be invoked when the button is clicked.

'css_class' -- The CSS class to use for the button, or 'None'.

make_button_for_url(title, url, css_class=None)

source code 

Generate HTML for a button.

Note that the caller is responsible for making sure the resulting button is placed within a form element.

'title' -- The button label.

'url' -- The URL to load when the button is clicked..

'css_class' -- The CSS class to use for the button, or 'None'.

get_session(request, session_id)

source code 

Retrieve the session corresponding to 'session_id'.

'request' -- A 'WebRequest' object for which to get the session.

raises -- 'InvalidSessionError' if the session ID is invalid, or is invalid for this 'request'.

handle_login(request, default_redirect_url='/')

source code 

Handle a login request.

Authenticate the login using the user name and password stored in the '_login_user_name' and '_login_password' request fields, respectively.

If authentication succeeds, redirect to the URL stored in the '_redirect_url' request field by raising an 'HttpRedirect', passing all other request fields along as well.

If '_redirect_url' is not specified in the request, the value of 'default_redirect_url' is used instead.

handle_logout(request, default_redirect_url='/')

source code 

Handle a logout request.

prerequisite -- 'request' must be in a valid session, which is ended.

After ending the session, redirect to the URL specified by the '_redirect_url' field of 'request'. If '_redirect_url' is not specified in the request, the value of 'default_redirect_url' is used instead.

generate_error_page(request, error_text)

source code 

Generate a page to indicate a user error.

'request' -- The request that was being processed when the error was encountered.

'error_text' -- A description of the error, as structured text.

returns -- The generated HTML source for the page.

generate_login_form(redirect_request, message=None)

source code 

Show a form for user login.

'message' -- If not 'None', a message to display to the user.

make_set_control(form_name, field_name, add_page, select_name=None, initial_elements=[], request=None, rows=6, width=200, window_width=480, window_height=240, ordered=0)

source code 

Construct a control for representing a set of items.

'form_name' -- The name of form in which the control is included.

'field_name' -- The name of the input control that contains an encoded representation of the set's elements. See 'encode_set_control_contents' and 'decode_set_control_contents'.

'select_name' -- The name of the select control that displays the elements of the set. If 'None', a control name is generated automatically.

'add_page' -- The URL for a popup web page that is displayed in response to the "Add..." button.

'initial_elements' -- The initial elements of the set.

'rows' -- The number of rows for the select control.

'width' -- The width of the select control.

'window_width', 'window_height' -- The width and height of the popup window for adding a new element.

'ordered' -- If true, controls are included for specifying the order of elements in the set.

encode_set_control_contents(values)

source code 

Encode 'values' for a set control.

'values' -- A sequence of values of elements of the set.

returns -- The encoded value for the control field.

decode_set_control_contents(content_string)

source code 

Decode the contents of a set control.

'content_string' -- The text of the form field containing the encoded set contents.

returns -- A sequence of the values of the elements of the set.

make_properties_control(form_name, field_name, properties, select_name=None)

source code 

Construct a control for representing a set of properties.

'form_name' -- The name of form in which the control is included.

'field_name' -- The name of the input control that contains an encoded representation of the properties. See 'encode_properties' and 'decode_properties'.

'properties' -- A map from property names to values of the properties to include in the control initially.

'select_name' -- The name of the select control that displays the elements of the set. If 'None', a control name is generated automatically.

encode_properties(properties)

source code 

Construct a URL-encoded representation of a set of properties.

'properties' -- A map from property names to values. Names must be URL-safe strings. Values are arbitrary strings.

returns -- A URL-encoded string representation of 'properties'.

This function is the inverse of 'decode_properties'.

decode_properties(properties)

source code 

Decode a URL-encoded representation of a set of properties.

'properties' -- A string containing URL-encoded properties.

returns -- A map from names to values.

This function is the inverse of 'encode_properties'.

make_help_link(help_text_tag, label='Help', **substitutions)

source code 

Make a link to pop up help text.

'help_text_tag' -- A message tag for the help diagnostic.

'label' -- The help link label.

'substitutions' -- Substitutions to the help diagnostic.

make_help_link_html(help_text, label='Help')

source code 

Make a link to pop up help text.

'help_text' -- HTML source for the help text.

'label' -- The help link label.

make_popup_page(message, buttons, title='')

source code 

Generate a popup dialog box page.

See 'make_popup_dialog_script' for an explanation of the parameters.

make_choose_control(field_name, included_label, included_items, excluded_label, excluded_items, item_to_text=<type 'str'>, item_to_value=<type 'str'>, ordered=0)

source code 

Construct HTML controls for selecting a subset.

The user is presented with two list boxes next to each other. The box on the left lists items included in the subset. The box on the right lists items excluded from the subset but available for inclusion. Between the boxes are buttons for adding and removing items from the subset.

If 'ordered' is true, buttons are also shown for reordering items in the included list.

'field_name' -- The name of an HTML hidden form field that will contain an encoding of the items included in the subset. The encoding consists of the values corresponding to included items, in a comma-separated list.

'included_label' -- HTML source for the label for the left box, which displays the included items.

'included_items' -- Items initially included in the subset. This is a sequence of arbitrary objects or values.

'excluded_label' -- HTML source for the label for the right box, which displays the items available for inclusion but not currently included.

'excluded_items' -- Items not initially included but available for inclusion. This is a sequence of arbitrary objects or values.

'item_to_text' -- A function that produces a user-visible text description of an item.

'item_to_value' -- A function that produces a value for an item, used as the value for an HTML option object.

'ordered' -- If true, additional controls are displayed to allow the user to manipulate the order of items in the included set.

returns -- HTML source for the items. Must be placed in a form.

make_button_for_popup(label, url, window_width=480, window_height=240)

source code 

Construct a button for displaying a popup page.

'label' -- The button label.

'url' -- The URL to display in the popup page.

returns -- HTML source for the button. The button must be placed within a form element.

format_color(red, green, blue)

source code 

Format an RGB color value for HTML.

'red', 'green', 'blue' -- Color values for respective channels, between 0.0 and 1.0. Values outside this range are truncated to this range.

make_submit_button(title='OK')

source code 

Generate HTML for a button to submit the current form.

'title' -- The button title.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler_test-module.html0000664000076400007640000001252511122067145030050 0ustar stefanstefan qm.test.classes.compiler_test
Package qm :: Package test :: Package classes :: Module compiler_test
[hide private]
[frames] | no frames]

Module compiler_test

source code

Classes [hide private]
  CompilationStep
A single compilation step.
  CompilerBase
A 'CompilerBase' is used by compilation test and resource clases.
  CompilerTest
A 'CompilerTest' tests a compiler.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dir_run_database.DirRunDatabase-class.html0000664000076400007640000003460311122067147033137 0ustar stefanstefan qm.test.classes.dir_run_database.DirRunDatabase
Package qm :: Package test :: Package classes :: Module dir_run_database :: Class DirRunDatabase
[hide private]
[frames] | no frames]

Class DirRunDatabase

source code

          object --+        
                   |        
 extension.Extension --+    
                       |    
run_database.RunDatabase --+
                           |
                          DirRunDatabase

A 'DirRunDatabase' reads test runs from a directory.

A 'DirRunDatabase' is associated with a given directory. The database consists of all '.qmr' files in the directory. Each '.qmr' file is treated as a result file.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, directory, database)
Create a new 'DirRunDatabase'.
source code
 
GetAllRuns(self)
Return all the 'TestRun's in the database.
source code

Inherited from run_database.RunDatabase: GetAnnotations, GetOutcomes, GetRunInTimeframe, GetRuns, GetRunsByAnnotations, GetTimeframe

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from extension.Extension: arguments, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, directory, database)
(Constructor)

source code 

Create a new 'DirRunDatabase'.

'directory' -- The path to the directory containing the results files.

'database' -- The test 'Database' to which the results files correspond.

Overrides: object.__init__

GetAllRuns(self)

source code 

Return all the 'TestRun's in the database.

returns -- A sequence consisting of all of the 'TestRun's in the database.

Overrides: run_database.RunDatabase.GetAllRuns
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-F.html0000664000076400007640000005162611122067144024304 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

F



qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.result-module.html0000664000076400007640000000207411122067144025641 0ustar stefanstefan result

Module result


Classes

Result

[hide private] ././@LongLink0000000000000000000000000000016100000000000011563 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database.ParameterDatabase.ParameterSuite-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.parameter_database.ParameterDatabase.ParameterSuit0000664000076400007640000004423411122067150033247 0ustar stefanstefan qm.test.parameter_database.ParameterDatabase.ParameterSuite
Package qm :: Package test :: Module parameter_database :: Class ParameterDatabase :: Class ParameterSuite
[hide private]
[frames] | no frames]

Class ParameterSuite

source code

         object --+        
                  |        
extension.Extension --+    
                      |    
            suite.Suite --+
                          |
                         ParameterDatabase.ParameterSuite

ParameterSuite represents a suite obtained from applying a given parameter to a suite from the wrapped DB.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, database, suite, parameter)
Construct a ParameterSuite.
source code
 
GetSuiteIds(self)
ParameterSuites contain ParameterSuites which wrap suites contained in the wrapped suite.
source code
 
GetTestIds(self)
ParameterSuites contain Tests obtained by applying the given parameter set to the tests contained in the wrapped suite.
source code
 
IsImplicit(self)
Return true if this is an implicit test suite.
source code

Inherited from suite.Suite: GetAllTestAndSuiteIds, GetDatabase, GetId

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from suite.Suite: EXTRA_DATABASE, EXTRA_ID, arguments, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, database, suite, parameter)
(Constructor)

source code 

Construct a ParameterSuite.

database -- The database this suite refers to.

suite -- The original suite this suite parametrizes.

parameter -- The value for the parameter to apply to the suite.

Overrides: object.__init__

GetSuiteIds(self)

source code 

ParameterSuites contain ParameterSuites which wrap suites contained in the wrapped suite.

Overrides: suite.Suite.GetSuiteIds

GetTestIds(self)

source code 

ParameterSuites contain Tests obtained by applying the given parameter set to the tests contained in the wrapped suite.

Overrides: suite.Suite.GetTestIds

IsImplicit(self)

source code 

Return true if this is an implicit test suite.

Implicit test suites cannot be edited.

Overrides: suite.Suite.IsImplicit
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Try.Try-class.html0000664000076400007640000003424211122067146031422 0ustar stefanstefan qm.external.DocumentTemplate.DT_Try.Try
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Try :: Class Try
[hide private]
[frames] | no frames]

Class Try

source code

Zope DTML Exception handling

usage:

<!--#try-->
<!--#except SomeError AnotherError-->
<!--#except YetAnotherError-->
<!--#except-->
<!--#else-->
<!--#/try-->

or:

<!--#try-->
<!--#finally-->
<!--#/try-->

The DTML try tag functions quite like Python's try command.

The contents of the try tag are rendered. If an exception is raised,
then control switches to the except blocks. The first except block to
match the type of the error raised is rendered. If an except block has
no name then it matches all raised errors.

The try tag understands class-based exceptions, as well as string-based
exceptions. Note: the 'raise' tag raises string-based exceptions.

Inside the except blocks information about the error is available via
three variables.

  'error_type' -- This variable is the name of the exception caught.

  'error_value' -- This is the caught exception's value.

  'error_tb' -- This is a traceback for the caught exception.

The optional else block is rendered when no exception occurs in the
try block. Exceptions in the else block are not handled by the preceding
except blocks.

The try..finally form specifies a `cleanup` block, to be rendered even
when an exception occurs. Note that any rendered result is discarded if
an exception occurs in either the try or finally blocks. The finally block
is only of any use if you need to clean up something that will not be
cleaned up by the transaction abort code.

The finally block will always be called, wether there was an exception in
the try block or not, or wether or not you used a return tag in the try
block. Note that any output of the finally block is discarded if you use a
return tag in the try block.

If an exception occurs in the try block, and an exception occurs in the
finally block, or you use the return tag in that block, any information
about that first exception is lost. No information about the first
exception is available in the finally block. Also, if you use a return tag
in the try block, and an exception occurs in the finally block or you use
a return tag there as well, the result returned in the try block will be
lost.

Original version by Jordan B. Baker.

Try..finally and try..else implementation by Martijn Pieters.

Instance Methods [hide private]
 
__init__(self, blocks) source code
 
render(self, md) source code
 
render_try_except(self, md) source code
 
render_try_finally(self, md) source code
 
find_handler(self, exception)
recursively search for a handler for a given exception
source code
 
match_base(self, exception, name) source code
 
__call__(self, md) source code
Class Variables [hide private]
  name = 'try'
  blockContinuations = ('except', 'else', 'finally')
  finallyBlock = None
  elseBlock = None
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.queue-pysrc.html0000664000076400007640000011214511122067163023563 0ustar stefanstefan qm.queue
Package qm :: Module queue
[hide private]
[frames] | no frames]

Source Code for Module qm.queue

  1  ######################################################################## 
  2  # 
  3  # File:   queue.py 
  4  # Author: Mark Mitchell 
  5  # Date:   01/07/2002 
  6  # 
  7  # Contents: 
  8  #   Queue 
  9  # 
 10  # Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Notes 
 18  ######################################################################## 
 19   
 20  # On systems that do not support threads, the Python Queue module 
 21  # does not work.  This is probably a bug in Python; if there are 
 22  # no threads, there is no difficulty in being threadsafe, and the 
 23  # module should simply omit the calls to acquire and release locks. 
 24  # This module is a manual implementation of this idea, with the 
 25  # limitation that the maxsize parameter to the initialization function 
 26  # must always be zero. 
 27   
 28  try: 
 29      import thread 
 30   
 31      # If we successfully imported the thread module, we can just use 
 32      # the builtin Queue. 
 33      from Queue import * 
 34  except: 
 35      # This code is based on the Python 2.2 Queue.py, but without 
 36      # the threading calls. 
37 - class Empty(Exception):
38 "Exception raised by Queue.get(block=0)/get_nowait()." 39 pass
40
41 - class Queue:
42 - def __init__(self, maxsize=0):
43 """Initialize a queue object with a given maximum size. 44 45 If maxsize is <= 0, the queue size is infinite. 46 """ 47 assert maxsize <= 0 48 self._init(maxsize)
49
50 - def qsize(self):
51 """Return the approximate size of the queue (not reliable!).""" 52 n = self._qsize() 53 return n
54
55 - def empty(self):
56 """Return 1 if the queue is empty, 0 otherwise (not reliable!).""" 57 n = self._empty() 58 return n
59
60 - def full(self):
61 """Return 1 if the queue is full, 0 otherwise (not reliable!).""" 62 n = self._full() 63 return n
64
65 - def put(self, item, block=1):
66 """Put an item into the queue. 67 68 If optional arg 'block' is 1 (the default), block if 69 necessary until a free slot is available. Otherwise (block 70 is 0), put an item on the queue if a free slot is immediately 71 available, else raise the Full exception. 72 """ 73 self._put(item)
74
75 - def put_nowait(self, item):
76 """Put an item into the queue without blocking. 77 78 Only enqueue the item if a free slot is immediately available. 79 Otherwise raise the Full exception. 80 """ 81 return self.put(item, 0)
82
83 - def get(self, block=1):
84 """Remove and return an item from the queue. 85 86 If optional arg 'block' is 1 (the default), block if 87 necessary until an item is available. Otherwise (block is 0), 88 return an item if one is immediately available, else raise the 89 Empty exception. 90 """ 91 if not block and not self.queue: 92 raise Empty 93 item = self._get() 94 return item
95
96 - def get_nowait(self):
97 """Remove and return an item from the queue without blocking. 98 99 Only get an item if one is immediately available. Otherwise 100 raise the Empty exception. 101 """ 102 return self.get(0)
103 104 # Override these methods to implement other queue organizations 105 # (e.g. stack or priority queue). 106 # These will only be called with appropriate locks held 107 108 # Initialize the queue representation
109 - def _init(self, maxsize):
110 self.maxsize = maxsize 111 self.queue = []
112
113 - def _qsize(self):
114 return len(self.queue)
115 116 # Check whether the queue is empty
117 - def _empty(self):
118 return not self.queue
119 120 # Check whether the queue is full
121 - def _full(self):
122 return self.maxsize > 0 and len(self.queue) == self.maxsize
123 124 # Put a new item in the queue
125 - def _put(self, item):
126 self.queue.append(item)
127 128 # Get an item from the queue
129 - def _get(self):
130 item = self.queue[0] 131 del self.queue[0] 132 return item
133

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.ssh_host.RSHHost-class.html0000664000076400007640000004532211122067147030145 0ustar stefanstefan qm.test.classes.ssh_host.RSHHost
Package qm :: Package test :: Package classes :: Module ssh_host :: Class RSHHost
[hide private]
[frames] | no frames]

Class RSHHost

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
              host.Host --+    
                          |    
                    SSHHost --+
                              |
                             RSHHost

An 'RSHHost' is an 'SSHHost' that uses 'rsh' instead of 'ssh'.

The reason that 'RSHHost' is a separate class is that (a) that makes it easier for users to construct an 'SSHHost', and (b) 'rsh' does not return the exit code of the remote program, so 'Run' requires adjustment.

Nested Classes [hide private]

Inherited from host.Host: Executable

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
Run(self, path, arguments, environment=None, timeout=-1)
Run a program on the remote host.
source code

Inherited from SSHHost: DeleteFile, DownloadFile, UploadFile

Inherited from SSHHost (private): _FormSCPCommandLine, _FormSSHCommandLine

Inherited from host.Host: UploadAndRun, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  ssh_program = TextField(default_value= "rsh", description= """...
  scp_program = TextField(default_value= "rcp", description= """...

Inherited from SSHHost: default_dir, host_name, nfs_dir, scp_args, ssh_args, user_name

Inherited from host.Host: kind

Inherited from extension.Extension: arguments

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Run(self, path, arguments, environment=None, timeout=-1)

source code 

Run a program on the remote host.

'path' -- The name of the program to run, on the remote host. If 'relative' is true, or if 'path' is not an absolute path but does contain at least one directory separator, then 'path' is interpreted relative to the default directory. Otherwise, 'path' is used unmodified.

'arguments' -- The sequence of arguments that should be passed to the program.

'environment' -- If not 'None', a dictionary of pairs of strings to add to the environment of the running program.

'timeout' -- The number of seconds the program is permitted to execute. After the 'timeout' expires, the program will be terminated. However, in some cases (such as when using 'rsh') it will be the local side of the connection that is closed. The remote side of the connection may or may not continue to operate, depending on the vagaries of the remote operating system.

returns -- A pair '(status, output)'. The 'status' is the exit status returned by the program, or 'None' if the exit status is not available. The 'output' is a string giving the combined standard output and standard error output from the program.

Overrides: host.Host.Run
(inherited documentation)

Class Variable Details [hide private]

ssh_program

Value:
TextField(default_value= "rsh", description= """The path to the remote\
 shell program.""")

scp_program

Value:
TextField(default_value= "rcp", description= """The path to the remote\
 copy program.""")

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.thread_target-module.html0000664000076400007640000001202411122067145030006 0ustar stefanstefan qm.test.classes.thread_target
Package qm :: Package test :: Package classes :: Module thread_target
[hide private]
[frames] | no frames]

Module thread_target

source code

Classes [hide private]
  LocalThread
A 'LocalThread' executes commands locally.
  ThreadTarget
A target implementation that runs tests in local threads.
qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.dejagnu_stream-module.html0000664000076400007640000000234011122067144030743 0ustar stefanstefan dejagnu_stream

Module dejagnu_stream


Classes

DejaGNUReader
DejaGNUStream

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.resource_adapter.ResourceAdapter-class.html0000664000076400007640000003520111122067150031771 0ustar stefanstefan qm.test.resource_adapter.ResourceAdapter
Package qm :: Package test :: Module resource_adapter :: Class ResourceAdapter
[hide private]
[frames] | no frames]

Class ResourceAdapter

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
          resource.Resource --+
                              |
                             ResourceAdapter

A 'ResourceAdapter' converts test classes to resource classes.

If 'C' is a test class, then a class derived from 'ResourceAdapter' and 'C' (in that order!) will be a resource class. The resource class 'Setup' method is equivalent to the 'Test' class 'Run' method. The 'CleanUp' action is empty.

Nested Classes [hide private]

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
SetUp(self, context, result)
Set up the resource.
source code

Inherited from resource.Resource: CleanUp

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]

Inherited from resource.Resource: kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, arguments, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

SetUp(self, context, result)

source code 

Set up the resource.

'context' -- A 'Context' giving run-time parameters to the resource. The resource may place additional variables into the 'context'; these variables will be visible to tests that depend on the resource.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

Overrides: resource.Resource.SetUp
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test_run-module.html0000664000076400007640000001107211122067145025402 0ustar stefanstefan qm.test.test_run
Package qm :: Package test :: Module test_run
[hide private]
[frames] | no frames]

Module test_run

source code

Classes [hide private]
  TestRun
A 'TestRun' stores the 'Result's from a single test run.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web-module.html0000664000076400007640000002505311122067145025074 0ustar stefanstefan qm.test.web.web
Package qm :: Package test :: Package web :: Module web
[hide private]
[frames] | no frames]

Module web

source code

Classes [hide private]
  Item
An 'Item' provides a convenient way to pass around named values.
  DefaultDtmlPage
Subclass of DTML page class for QMTest pages.
  QMTestPage
A 'QMTestPage' is a 'DtmlPage' for pages generated by QMTest.
  QMTestReportPage
A 'QMTestReportPage' is a 'DtmlPage' for pages generated by QMTest.
  ContextPage
DTML page for setting the context.
  DirPage
A test database directory page.
  DirReportPage
A run database directory page.
  ShowItemReportPage
DTML page for showing tests and resources.
  LoadContextPage
DTML page for uploading a context.
  LoadExpectationsPage
DTML page for uploading a context.
  LoadResultsPage
DTML page for uploading a context.
  NewItemPage
Page for creating a new test or resource.
  NewSuitePage
Page for creating a new test suite.
  ResultPage
DTML page for showing result detail.
  SetExpectationPage
DTML page for setting the expectation associated with a test.
  ShowItemPage
DTML page for showing and editing tests and resources.
  ShowSuitePage
Page for displaying the contents of a test suite.
  StorageResultsStream
A 'StorageResultsStream' stores results.
  TestResultsPage
DTML page for displaying test results.
  QMTestServer
A 'QMTestServer' is the web GUI interface to QMTest.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.previous_testrun-module.html0000664000076400007640000001134211122067145030633 0ustar stefanstefan qm.test.classes.previous_testrun
Package qm :: Package test :: Package classes :: Module previous_testrun
[hide private]
[frames] | no frames]

Module previous_testrun

source code

Classes [hide private]
  PreviousTestRun
A 'PreviousTestRun' uses test results as expectations.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compiler_table-pysrc.html0000664000076400007640000014741211122067162030036 0ustar stefanstefan qm.test.classes.compiler_table
Package qm :: Package test :: Package classes :: Module compiler_table
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.compiler_table

  1  ######################################################################## 
  2  # 
  3  # File:   compiler_table.py 
  4  # Author: Mark Mitchell 
  5  # Date:   04/16/2003 
  6  # 
  7  # Contents: 
  8  #   CompilerTable 
  9  # 
 10  # Copyright (c) 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  ######################################################################## 
 13   
 14  """Support for compiler test databases. 
 15   
 16  This module contains the 'CompilerTable' resource class which can be 
 17  used by compiler test databases to determine which compiler to test 
 18  based on context variables provided by the user.""" 
 19   
 20  ######################################################################## 
 21  # Imports 
 22  ######################################################################## 
 23   
 24  import compiler 
 25  import qm 
 26  from   qm.test.database import get_database 
 27  from   qm.test.resource import Resource 
 28  from   local_host import LocalHost 
 29   
 30  ######################################################################## 
 31  # Classes 
 32  ######################################################################## 
 33   
34 -class CompilerTable(Resource):
35 """A map from programming languages to 'Compiler's. 36 37 The 'CompilerTable' resource uses the context to determine which 38 compilers the user wants to test. Test databases containing 39 compiler tests should arrange for the tests they compain to depend 40 on a 'CompilerTable' resource. 41 42 The first context variable which is examined is 43 'CompilerTable.languages'. The value should be a 44 whitespace-separated list of programming language names. (See 45 below for standardized names for some languages.) 46 47 Then, for each language 'l' in the list of languages, the 48 following context variables are examined: 49 50 - 'CompilerTable.l_kind' 51 52 The kind of compiler (e.g., "GCC" or "EDG") used to compile 53 programs of language 'l'. The 'kind' must name a class derived 54 from 'Compiler'. 55 56 - 'CompilerTable.l_path' 57 58 The path to the compiler for language 'l'. This path may be 59 either absolute or relative. 60 61 - 'CompilerTable.l_options' 62 63 A whitespace-separated list of command-line options to provide 64 to the compiler for language 'l'. These options are passed to 65 the constructor for the 'Compiler' object; generally, all tests 66 are run with these options, followed by any test-specific 67 options. For example, if the user wants to test the compiler 68 when run with '-O2', the user would put '-O2' in the 'l_options' 69 context variable. 70 71 The 'CompilerTable' resource provides the following context 72 variables to all tests that depend upon the resource: 73 74 - 'CompilerTable.compilers' 75 76 The 'compilers' variable is a map from language names to 77 instances of 'Compiler'. Test classes should obtain the 78 'Compiler' to use when compiling source files by using this 79 map. 80 81 - 'CompilerTable.target' 82 83 An instance of 'Host' that can be used to run compiler 84 programs.""" 85 86 LANG_C = "c" 87 """The name of the C programming language.""" 88 89 LANG_CPLUSPLUS = "cplusplus" 90 """The name of the C++ programming language.""" 91
92 - def SetUp(self, context, result):
93 94 # There are no compilers yet. 95 compilers = {} 96 97 # See what programming languages are supported. 98 languages = context["CompilerTable.languages"].split() 99 100 # For each language, create a Compiler. 101 for l in languages: 102 # Retrieve information from the context. 103 kind = context["CompilerTable." + l + "_kind"].strip() 104 path = context["CompilerTable." + l + "_path"].strip() 105 # Look for (optional) command-line options. 106 opts = context.get("CompilerTable." + l + "_options", 107 "").split() 108 ldflags = context.get("CompilerTable." + l + "_ldflags", 109 "").split() 110 # Find the Python class corresponding to this compiler. 111 compiler_class = compiler.__dict__[kind] 112 # Instantiate the compiler. 113 c = compiler_class(path, opts) 114 c.SetLDFlags(ldflags) 115 # Store it in the compilers map. 116 compilers[l] = c 117 118 # Make the table available to tests. 119 context["CompilerTable.compilers"] = compilers 120 121 # For backwards compatibility, we recognize this old 122 # context variable here. 123 interpreter = context.get("CompilerTest.interpreter") 124 if interpreter: 125 interpreter = interpreter.split() 126 arguments = { simulator : interpreter[0], 127 simulator_args : interpreter[1:] } 128 target = qm.test.classes.Simulator(arguments) 129 else: 130 target_desc = context.get("CompilerTable.target") 131 if target_desc is None: 132 target = LocalHost({}) 133 else: 134 f = lambda n: qm.test.base.get_extension_class(n, "host", 135 get_database()) 136 host_class, arguments \ 137 = qm.extension.parse_descriptor(target_desc.strip(), f) 138 target = host_class(arguments) 139 context["CompilerTable.target"] = target
140

qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-B.html0000664000076400007640000002430711122067144024274 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

B



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.extension.Extension.Type-class.html0000664000076400007640000002156311122067146027317 0ustar stefanstefan qm.extension.Extension.Type
qm :: extension :: Extension :: Class Extension :: Class Type
[hide private]
[frames] | no frames]

Type Type

source code

object --+    
         |    
      type --+
             |
            Extension.Type

Instance Methods [hide private]
 
__init__(cls, name, bases, dict)
Generate an '_argument_dictionary' holding all the 'Field' objects.
source code

Inherited from type: __call__, __cmp__, __delattr__, __getattribute__, __hash__, __new__, __repr__, __setattr__, __subclasses__, mro

Inherited from object: __reduce__, __reduce_ex__, __str__

Properties [hide private]

Inherited from type: __base__, __bases__, __basicsize__, __dictoffset__, __flags__, __itemsize__, __mro__, __name__, __weakrefoffset__

Inherited from object: __class__

Method Details [hide private]

__init__(cls, name, bases, dict)
(Constructor)

source code 

Generate an '_argument_dictionary' holding all the 'Field' objects. Then replace 'Field' objects by their values for convenient use inside the code.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.previous_testrun-module.html0000664000076400007640000000216411122067144031417 0ustar stefanstefan previous_testrun

Module previous_testrun


Classes

PreviousTestRun

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.platform-module.html0000664000076400007640000000251211122067144025166 0ustar stefanstefan platform

Module platform


Classes

MailError

Functions

get_shell_for_command
get_shell_for_script

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.simulator-pysrc.html0000664000076400007640000006744311122067156027104 0ustar stefanstefan qm.test.classes.simulator
Package qm :: Package test :: Package classes :: Module simulator
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.simulator

 1  ######################################################################## 
 2  # 
 3  # File:   simulator.py 
 4  # Author: Mark Mitchell 
 5  # Date:   2005-06-03 
 6  # 
 7  # Contents: 
 8  #   Simulator 
 9  # 
10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ####################################################################### 
17   
18  from local_host import LocalHost 
19  from qm.fields import TextField, SetField 
20   
21  ######################################################################## 
22  # Classes 
23  ####################################################################### 
24   
25 -class Simulator(LocalHost):
26 """A 'Simulator' is a semi-hosted simulation environment. 27 28 The local file system is shared with the simulated machine. A 29 simulator is used to execute programs.""" 30 31 simulator = TextField( 32 description = """The simulation program.""" 33 ) 34 35 # Any arguments that must be provided to the simulator. 36 simulator_args = SetField( 37 TextField(description = """Arguments to the simulation program.""")) 38
39 - def Run(self, path, arguments, environment = None, timeout = -1):
40 41 arguments = self.simulator_args + [path] + arguments 42 return super(Simulator, self.Run(self.simulator, 43 arguments, 44 environment, 45 timeout))
46

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.execution_thread-module.html0000664000076400007640000001117211122067145027072 0ustar stefanstefan qm.test.execution_thread
Package qm :: Package test :: Module execution_thread
[hide private]
[frames] | no frames]

Module execution_thread

source code

Classes [hide private]
  ExecutionThread
A 'ExecutionThread' executes tests in a separate thread.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.explicit_suite-module.html0000664000076400007640000001133711122067145030231 0ustar stefanstefan qm.test.classes.explicit_suite
Package qm :: Package test :: Package classes :: Module explicit_suite
[hide private]
[frames] | no frames]

Module explicit_suite

source code

Classes [hide private]
  ExplicitSuite
An 'ExplicitSuite' stores all of the test and suite ids explicitly.
qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.ContextPage-class.html0000664000076400007640000003241611122067151027132 0ustar stefanstefan qm.test.web.web.ContextPage
Package qm :: Package test :: Package web :: Module web :: Class ContextPage
[hide private]
[frames] | no frames]

Class ContextPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      ContextPage

DTML page for setting the context.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server)
Construct a new 'ContextPage'.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server)
(Constructor)

source code 

Construct a new 'ContextPage'.

'server' -- The 'QMTestServer' creating this page.

Overrides: web.DtmlPage.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.structured_text-pysrc.html0000664000076400007640000105116111122067162025707 0ustar stefanstefan qm.structured_text
Package qm :: Module structured_text
[hide private]
[frames] | no frames]

Source Code for Module qm.structured_text

  1  ######################################################################## 
  2  # 
  3  # File:   structured_text.py 
  4  # Author: Alex Samuel 
  5  # Date:   2001-03-04 
  6  # 
  7  # Contents: 
  8  #   Code for processing structured text. 
  9  # 
 10  # Copyright (c) 2001, 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  """Functions for parsing, processing, and formatting Python structured text. 
 17   
 18  See "Structured Text Formatting 
 19  Rules":http://www.python.org/sigs/doc-sig/stext.html for more 
 20  information. 
 21  """ 
 22   
 23  ######################################################################## 
 24  # imports 
 25  ######################################################################## 
 26   
 27  import cStringIO 
 28  import htmlentitydefs 
 29  import re 
 30  import string 
 31  import sys 
 32   
 33  ######################################################################## 
 34  # constants 
 35  ######################################################################## 
 36   
 37  html_help_text = ''' 
 38  <h4>Structured Text</h4> 
 39   
 40  <p>Structured text is a simple set of conventions for formatting 
 41  ordinary text.  Usually, you can simply type ordinary text where QM 
 42  expects structured text; the resulting output will be line-wrapped, with 
 43  paragraph breaks indicated by blank lines.</p> 
 44   
 45  <p>Structured text also provides simple ways of adding elements such as 
 46  bulleted and numbered lists, bold and italics text, monospaced text, and 
 47  hyperlinks to ordinary text.  For example, to obtain bold text, place a 
 48  pair of asterisks on either side of it.  Thus, 
 49  <blockquote><pre> 
 50  **hello, there** 
 51  </pre></blockquote> 
 52  is displayed as 
 53  <blockquote> 
 54  <b>hello, there</b> 
 55  </blockquote>Structured text may be displayed as HTML, as plain text, 
 56  or in other formats.  The exact format of the output will depend on the 
 57  capabilities of the output system.</p> 
 58   
 59  <p>For a complete description of structured text rules, see the 
 60  <a href="http://www.python.org/sigs/doc-sig/stext.html">Structured Text 
 61  Formatting Rules</a>.</p> 
 62  ''' 
 63   
 64  ######################################################################## 
 65  # classes 
 66  ######################################################################## 
 67   
68 -class Formatter:
69 """Interface for output formatters for the 'StructuredTextProcessor'. 70 71 Valid list environment types are 72 73 * definition list 74 75 * ordered list 76 77 * paragraph 78 79 * unordered list 80 81 Valid styles are 82 83 * emphasized 84 85 * strong 86 87 * underlined 88 89 * literal 90 91 * verbatim 92 93 """ 94 95 pass
96 97 98
99 -class TextFormatter(Formatter):
100 """Formatter for generating plain text from structured text.""" 101 102 __style_markers = { 103 "emphasized" : "*", 104 "strong" : "**", 105 "underlined" : "_", 106 "literal" : "'", 107 "verbatim" : "'''", 108 } 109 110
111 - def __init__(self, 112 output_file=sys.stdout, 113 width=78, 114 indent_size=2, 115 indent=0, 116 list_bullet="-"):
117 """Create a new HTML formatter. 118 119 'output_file' -- A file object to which HTML source is 120 written.""" 121 122 self.__output_file = output_file 123 self.__width = width 124 self.__col = 0 125 self.__indent = indent 126 self.__indent_size = indent_size 127 self.__list_bullet = list_bullet 128 self.__list_depth = 0 129 self.__current_link_target = None 130 self.__link_targets = []
131 132
133 - def End(self):
134 """End the processed text document.""" 135 136 # If there were any hyperlink references placed, we need to list 137 # the link targets at the end of the document. 138 if self.__link_targets: 139 self.__NextLine() 140 for index in range(0, len(self.__link_targets)): 141 # Print the reference number and link target, one to a 142 # line. 143 target = self.__link_targets[index] 144 self.WriteText("[%d] %s" % (index + 1, target)) 145 self.__NextLine()
146 147
148 - def WriteText(self, text):
149 """Write ordinary text.""" 150 151 # Split the text into words. Use 're.split' and grouping 152 # around the separator so that the resulting list contains 153 # elements for the separators, too. 154 words = re.split("( )", text) 155 # Remove empty strings. 156 words = filter(None, words) 157 # Loop over words. 158 start_of_line = 0 159 for word in words: 160 # Does this word fit on the line? 161 if self.__col + len(word) > self.__width: 162 # No. Go to the next line. 163 self.__NextLine() 164 self.__IndentTo(self.__indent) 165 start_of_line = 1 166 # Are we at the beginning of a line? 167 if start_of_line: 168 if string.strip(word) == "": 169 # Don't print spaces at the start of a line. 170 continue 171 else: 172 # No longer. 173 start_of_line = 0 174 # Write the word. 175 self.__Write(word)
176 177
178 - def StartList(self, type):
179 """Start a list environment of type 'type'.""" 180 181 # Bump up indentation for paragraphs, except for the outermost 182 # level. 183 if type == "paragraph" and self.__list_depth > 0: 184 self.__indent = self.__indent + self.__indent_size 185 # Keep track of the nesting depth of lists. 186 self.__list_depth = self.__list_depth + 1
187 188
189 - def EndList(self, type):
190 """End a list environment of type 'type'.""" 191 192 # Keep track of the nesting depth of lists. 193 self.__list_depth = self.__list_depth - 1 194 # Bump back indentation when ending paragraph lists, except for 195 # the outermost level. 196 if type == "paragraph" and self.__list_depth > 0: 197 self.__indent = self.__indent - self.__indent_size
198 199
200 - def StartItem(self, type, label=None):
201 """Begin an element to the environment of type 'type'. 202 203 'label' -- If type is "ordered list", this is the label for 204 this list element.""" 205 206 self.__IndentTo(self.__indent) 207 # For list items, emit the appopriate item tag. 208 if type == "ordered list": 209 self.__Write("%s " % label) 210 elif type == "unordered list": 211 self.__Write("%s " % self.__list_bullet) 212 elif type == "definition list": 213 pass
214 215
216 - def FinishDefinedTerm(self):
217 """Finish the definition of a term in a definition list.""" 218 219 self.__Write(" -- ");
220 221
222 - def EndItem(self, type):
223 """End an element in the environment of type 'type'.""" 224 225 if type == "paragraph": 226 # End a paragraph. End this line if we've started writing 227 # on it. 228 if self.__col > self.__indent: 229 self.__NextLine() 230 # Skip another line. 231 self.__NextLine()
232 233
234 - def StartStyle(self, style):
235 """Start a new text style 'style'.""" 236 237 self.__Write(self.__style_markers[style])
238 239
240 - def EndStyle(self, style):
241 """End the text style 'style'.""" 242 243 self.__Write(self.__style_markers[style])
244 245 254 255 276 277 278 # Helper methods. 279
280 - def __IndentTo(self, col):
281 if col > self.__col: 282 self.__Write(" " * (col - self.__col))
283 284
285 - def __Write(self, text):
286 self.__output_file.write(text) 287 self.__col = self.__col + len(text)
288 289
290 - def __NextLine(self):
291 self.__Write("\n") 292 self.__col = 0
293 294 295
296 -class HtmlFormatter(Formatter):
297 """Formatter for generating HTML from structured text.""" 298 299 __start_list_tags = { 300 "definition list": "<dl>\n", 301 "ordered list": "<ol>\n", 302 "paragraph": "", 303 "unordered list": "<ul>\n", 304 "verbatim": "", 305 } 306 307 __end_list_tags = { 308 "definition list": "</dl>\n", 309 "ordered list": "</ol>\n", 310 "paragraph": "", 311 "unordered list": "</ul>\n", 312 "verbatim": "", 313 } 314 315 __start_item_tags = { 316 "definition list": "<dt>", 317 "ordered list": "<li>\n", 318 "paragraph": "<p>", 319 "unordered list": "<li>\n", 320 "verbatim": "", 321 } 322 323 __end_item_tags = { 324 "definition list": "</dd>\n", 325 "ordered list": "</li>\n", 326 "paragraph": "</p>\n", 327 "unordered list": "</li>\n", 328 "verbatim": "", 329 } 330 331 __start_style_tags = { 332 "emphasized": "<em>", 333 "strong": "<strong>", 334 "underlined": "<u>", 335 "literal": "<tt>", 336 "verbatim": '<pre>\'<span class="verbatim">', 337 } 338 339 __end_style_tags = { 340 "emphasized": "</em>", 341 "strong": "</strong>", 342 "underlined": "</u>", 343 "literal": "</tt>", 344 "verbatim": '</span>\'</pre>', 345 } 346 347
348 - def __init__(self, output_file=sys.stdout):
349 """Create a new HTML formatter. 350 351 'output_file' -- A file object to which HTML source is 352 written.""" 353 354 self.__output_file = output_file
355 356
357 - def End(self):
358 """End the processed text document.""" 359 360 pass
361 362
363 - def WriteText(self, text):
364 """Write ordinary text.""" 365 366 text = escape_html_entities(text) 367 self.__Write(text)
368 369
370 - def StartList(self, type):
371 """Start a list environment of type 'type'.""" 372 373 self.__Write(self.__start_list_tags[type])
374 375
376 - def EndList(self, type):
377 """End a list environment of type 'type'.""" 378 379 self.__Write(self.__end_list_tags[type])
380 381
382 - def StartItem(self, type, label=None):
383 """Begin an element to the environment of type 'type'. 384 385 'label' -- If type is "ordered list", this is the label for 386 this list element.""" 387 388 self.__Write(self.__start_item_tags[type])
389 390
391 - def FinishDefinedTerm(self):
392 """Finish the definition of a term in a definition list.""" 393 394 self.__Write("</dt><dd>\n");
395 396
397 - def EndItem(self, type):
398 """End an element in the environment of type 'type'.""" 399 400 self.__Write(self.__end_item_tags[type])
401 402
403 - def StartStyle(self, style):
404 """Start a new text style 'style'.""" 405 406 self.__Write(self.__start_style_tags[style])
407 408
409 - def EndStyle(self, style):
410 """End the text style 'style'.""" 411 412 self.__Write(self.__end_style_tags[style])
413 414 419 420 425 426 427 # Helper methods. 428
429 - def __Write(self, text):
430 self.__output_file.write(text)
431 432 433
435 """Parser and formatter for Python structured text.""" 436 437 # Regex fragment matching a single punctuation or space character. 438 __punctuation = "[%s]" % "][)(.,!?;:'\" " 439 440 # Regex matching a list bullet at the start of the line. 441 __bullet_regex = re.compile("^[-o*] +") 442 443 # Regex matching a sequence label at the start of the line. 444 __sequence_regex = re.compile("^([A-Za-z]+\.|[0-9]+\.?)+ +") 445 446 # Regex matching a definition label at the start of the line. 447 # Group 1 is the defined term. 448 __definition_regex = re.compile("^(.*) +-- +") 449 450 # Regex matching newslines plus any spaces on either side. 451 __collapse_regex = re.compile(" *\n *", re.MULTILINE) 452 453 # Regex matching indentation at the beginning of a line. 454 __indent_regex = re.compile("^ *") 455 456 # Regex matching single-quoted literal text. Group 1 is leading 457 # spaces; group 2 is the verbatim text; group 3 is trailing spaces 458 # and/or punctuation. 459 __literal_regex = re.compile("( +|^)'([^']+)'(%s+|$)" % __punctuation) 460 461 # Regex matching emphasized text. Group 1 is leading spaces; 462 # group 2 is the verbatim text; group 3 is trailing spaces and/or 463 # punctuation. 464 __strong_regex = re.compile("( +|^)\*\*([^*]+)\*\*(%s+|$)" % __punctuation) 465 466 # Regex matching strong text. Group 1 is leading spaces; group 2 467 # is the verbatim text; group 3 is trailing spaces and/or 468 # punctuation. 469 __emph_regex = re.compile("( +|^)\*([^*]+)\*(%s+|$)" % __punctuation) 470 471 # Regex matching underlined text. Group 1 is leading spaces; 472 # group 2 is the verbatim text; group 3 is trailing spaces and/or 473 # punctuation. 474 __underline_regex = re.compile("( +|^)_([^_]+)_(%s+|$)" % __punctuation) 475 476 # Regex matching double-quoted text that may be a hyperlink. If 477 # there is a matching link footnote, the contents of the double 478 # quotes, group 1, is a hyperlink. 479 __link_regex = re.compile('"([^"]*)"') 480 481 # Regex matching hyperlink footnotes. Group one is the link text; 482 # group 2 is the link target URL. 483 __link_footnote_regex = re.compile('\n\\.\\. *"([^"]*)" *([^ \n]*)[^\n]*') 484 485 # List types which may not include other environments nested 486 # inside their items. 487 __non_nestable_types = [ 488 "paragraph", 489 ] 490 491
492 - def __init__(self, formatter):
493 """Create a new structured text processor. 494 495 'formatter' -- The formatter to use to generate output.""" 496 497 self.__stack = [] 498 self.__formatter = formatter 499 self.__hyperlinks = {}
500 501
502 - def NormalizeSpaces(self, text):
503 """Return 'text' with spaces normalized.""" 504 505 # Convert tabs to spaces. 506 text = string.replace(text, "\t", " ") 507 # Normalize leading and trailing whitespace. 508 return string.strip(text) + " "
509 510
511 - def __call__(self, text):
512 """Process structured text 'text'.""" 513 514 # Look for hyperlink footnotes, and build a map of hyperlinked 515 # phrases. Keep track of where the last match was. 516 position = 0 517 while position < len(text): 518 # Look for the next hyperlink footnote match. 519 match = self.__link_footnote_regex.search(text[position:]) 520 if match is None: 521 # No more; all done. 522 break 523 else: 524 # Record the hyperlink. 525 link_text = string.strip(match.group(1)) 526 link_target = match.group(2) 527 self.__hyperlinks[link_text] = link_target 528 # Remove the footnote from the text. 529 text = text[:match.start() + position] \ 530 + text[match.end() + position:] 531 # Next, try searching from the text following the match. 532 position = match.start() 533 534 # Split text into paragraphs. 535 paragraphs = get_paragraphs(text) 536 537 # Loop over paragraphs. 538 for paragraph in paragraphs: 539 # If this is a verbatim paragraph, handle it specially. 540 match = _verbatim_regexp.match(paragraph) 541 if match: 542 if self.__stack: 543 indentation = self.__stack[-1][1] 544 else: 545 indentation = 0 546 self.__SetType("verbatim", indentation) 547 self.__formatter.StartStyle("verbatim") 548 self.__formatter.WriteText(match.group(1)[3:-3]) 549 self.__formatter.EndStyle("verbatim") 550 continue 551 # Extract indentations for all the lines in the paragraph. 552 indents = self.__indent_regex.findall(paragraph) 553 # The paragraph's indentation is the minimum indentation 554 # of its lines. 555 indentation = min(map(len, indents)) 556 # Trim indentation from the first line. 557 paragraph = paragraph[indentation:] 558 559 # Skip empty paragraphs. 560 if paragraph == "": 561 continue 562 563 # Grab the first line of the paragraph. 564 first_line = string.split(paragraph, "\n", 1)[0] 565 566 # Does it look like a bullet (unordered) list item? 567 match = self.__bullet_regex.match(first_line) 568 if match is not None: 569 # Yes. Put the formatter into an unordered list 570 # environment. 571 self.__SetType("unordered list", indentation) 572 # Cut off the bullet, and use the indentation of the 573 # text itself. 574 match_length = len(match.group(0)) 575 indentation = indentation + match_length 576 paragraph = paragraph[match_length:] 577 else: 578 # Does it look like a sequence label of an ordered list? 579 match = self.__sequence_regex.match(first_line) 580 if match is not None: 581 # Yes. Put the formatter into an ordered list 582 # environment. 583 self.__SetType("ordered list", indentation, 584 label=match.group(1)) 585 # Cut off the label, and use the indentation of 586 # the text itself. 587 match_length = len(match.group(0)) 588 indentation = indentation + match_length 589 paragraph = paragraph[match_length:] 590 else: 591 match = self.__definition_regex.match(first_line) 592 # Does it look like a definition list item? 593 if match is not None: 594 # Yes. Put the formatter into a definition 595 # list environment. 596 self.__SetType("definition list", indentation, 597 label=match.group(1)) 598 # Cut off the defined term label, and use the 599 # indentation of the definition. 600 match_length = len(match.group(0)) 601 indentation = indentation + match_length 602 paragraph = paragraph[match_length:] 603 604 # Collapse the remaining paragraph into a single line of 605 # text by replacing newlines with spaces. 606 paragraph = self.__collapse_regex.sub(" ", paragraph) 607 # Clean up spacing. 608 paragraph = self.NormalizeSpaces(paragraph) 609 # Now generate a paragraph for the rest of the text. 610 self.__SetType("paragraph", indentation) 611 self.__WriteText(paragraph)
612 613
614 - def End(self):
615 """Stop processing text, and do any necessary cleanup.""" 616 617 # Pop out of any remaining environments. 618 while self.__stack: 619 top_type, top_indentation = self.__stack[-1] 620 # End the item. 621 self.__formatter.EndItem(top_type) 622 # End the environment. 623 self.__PopType() 624 # Finish up the formatter. 625 self.__formatter.End()
626 627 628 # Helper methods. 629
630 - def __PushType(self, type, indentation):
631 """Start a new environment.""" 632 633 # The innermost environment may be of a type that cannot 634 # contain nested environments in its items. If that's the 635 # case, end the item here. 636 if len(self.__stack) > 0: 637 top_type, top_indentation = self.__stack[-1] 638 if top_type in self.__non_nestable_types: 639 self.__formatter.EndItem(top_type) 640 # Start te environment. 641 self.__formatter.StartList(type) 642 # Push it onto the stack. 643 self.__stack.append((type, indentation))
644 645
646 - def __PopType(self):
647 """End and remove the innermost environment.""" 648 649 # Get the topmost environment on the stack. 650 top_type, top_indentation = self.__stack[-1] 651 # End the environment. 652 self.__formatter.EndList(top_type) 653 # Remove it from the stack. 654 self.__stack.pop() 655 # The new innermost environment may be of a type that cannot 656 # contain nested environments. If it is, then we 657 # (prematurely) ended an item when we opened the environment 658 # that just closed. We'll have to open a new item here. 659 if len(self.__stack) > 0: 660 top_type, top_indentation = self.__stack[-1] 661 if top_type in self.__non_nestable_types: 662 self.__formatter.StartItem(top_type)
663 664
665 - def __SetType(self, type, indentation, label=None):
666 """Set the environment type and indentation level.""" 667 668 while 1: 669 # Look at the current innermost environment (if there is 670 # eone). 671 if len(self.__stack) == 0: 672 top_indentation = -1 673 else: 674 top_type, top_indentation = self.__stack[-1] 675 676 # Are we outdented from the current environment and 677 # indentation level, or at the same indentation? 678 if indentation <= top_indentation: 679 # End the previous item. 680 self.__formatter.EndItem(top_type) 681 if indentation < top_indentation: 682 # We're outdented, so end the previous environment. 683 self.__PopType() 684 elif top_type != type: 685 # Same indentation but different environment type. 686 # End the previous environment, and start a new 687 # one. 688 self.__PopType() 689 self.__PushType(type, indentation) 690 else: 691 # Same indentation, same environment. We just 692 # need a new item, so fall through. 693 break 694 else: 695 # We're indented. Nest a new environment in the 696 # current item. 697 self.__PushType(type, indentation) 698 break 699 700 # Start a new item in the current environment. 701 self.__formatter.StartItem(type, label) 702 if type == "definition list": 703 self.__WriteText(label) 704 self.__formatter.FinishDefinedTerm()
705 706
707 - def __WriteText(self, text):
708 """Write paragraph text.""" 709 710 # Look for various types of markup for special formatting for 711 # a range of text. 712 for regex, style in [ 713 (self.__literal_regex, "literal"), 714 (self.__strong_regex, "strong"), 715 (self.__emph_regex, "emphasized"), 716 (self.__underline_regex, "underlined"), 717 ]: 718 # Find the first match. 719 match = regex.search(text) 720 if match is not None: 721 # Found a match. Recursively format everything up to 722 # the start of the match. 723 self.__WriteText(text[:match.end(1)]) 724 # Start generating text in the indicated style. 725 self.__formatter.StartStyle(style) 726 # If it's a literal style, push the literal text out 727 # directly. Otherwise, format it recursively. 728 if style == "literal" or style == "verbatim": 729 self.__formatter.WriteText(match.group(2)) 730 else: 731 self.__WriteText(match.group(2)) 732 # Stop generating text in the specified style. 733 self.__formatter.EndStyle(style) 734 # Recursively format everything following the match. 735 self.__WriteText(text[match.start(3):]) 736 return 737 738 # Look for hyperlink markup. 739 match = self.__link_regex.search(text) 740 if match is not None: 741 link_text = string.strip(match.group(1)) 742 # Is there a footnote providing a link target for this 743 # phrase? 744 if self.__hyperlinks.has_key(link_text): 745 # Yes. Emit a hyperlink. 746 link_target = self.__hyperlinks[link_text] 747 # Recursively format everything up to the start of the 748 # match. 749 self.__WriteText(text[:match.start(0)]) 750 # Generate the start of the link. 751 self.__formatter.StartLink(link_target) 752 # Recursively format the link text. 753 self.__WriteText(match.group(1)) 754 # End the link. 755 self.__formatter.EndLink() 756 # Recursively format everything following the match. 757 self.__WriteText(text[match.end(1) + 1:]) 758 return 759 else: 760 # Fall through and format the entire text as usual. 761 pass 762 763 # Nothing special. Write ordinary text. 764 self.__formatter.WriteText(text)
765 766 767 ######################################################################## 768 # functions 769 ######################################################################## 770
771 -def escape_html_entities(text):
772 """Return 'text' with special characters converted to HTML entities.""" 773 774 return __entity_char_regex.sub(__entity_char_replacement, text)
775 776
777 -def __format(text, formatter):
778 """Process structured text 'text' with 'formatter'.""" 779 780 processor = StructuredTextProcessor(formatter) 781 processor(text) 782 processor.End()
783 784
785 -def to_html(structured_text):
786 """Return 'structured_text' formatted as HTML.""" 787 788 # Create an HTML formatter that dumps its output to a StringIO. 789 output_string = cStringIO.StringIO() 790 formatter = HtmlFormatter(output_string) 791 # Generate output. 792 __format(structured_text, formatter) 793 # Return the resulting text. 794 return output_string.getvalue()
795 796
797 -def to_text(structured_text, width=78, indent=0):
798 """Return 'structured_text' formatted as plain text. 799 800 'width' -- The width of the text (including the indentation). 801 802 'indent' -- The width of the block indentation of the formatted 803 output.""" 804 805 # Create a text formatter that dumps its output to a StringIO. 806 output_string = cStringIO.StringIO() 807 formatter = TextFormatter(output_string, width=width, indent=indent) 808 # Generate output. 809 __format(structured_text, formatter) 810 # Return the resulting text. 811 return output_string.getvalue()
812 813
814 -def get_first(structured_text):
815 """Return the first line of 'structured_text'. 816 817 By convention, the first line of a structured text description is a 818 short summary.""" 819 820 return string.split(structured_text, "\n", 1)[0]
821 822
823 -def get_rest(structured_text):
824 """Return the contents of 'structured_text' minus the first line.""" 825 826 parts = string.split(structured_text, "\n", 1) 827 # There may not be more than one line; handle this gracefully. 828 if len(parts) > 0: 829 return parts[1] 830 else: 831 return ""
832 833
834 -def get_paragraphs(structured_text):
835 """Split 'structured_text' into paragraphs. 836 837 'structured_text' -- A string consisting of structured text. 838 839 returns -- A sequence of pagraphs of structured text. Each 840 element in the sequence corresponds to a successive pagraph 841 in the 'structured_text'. If 'structured_text' is the empty 842 string, the sequence returned will consist of a single 843 paragraph, itself empty.""" 844 845 # There are no paragraphs yet. 846 paragraphs = [] 847 # The first paragraph begins at the first character. 848 begin = 0 849 # We have not yet found the end of the paragraph. 850 end = 0 851 # Keep going until there is no more text. 852 while end < len(structured_text): 853 # If we are at the start of a paragraph, check to see if 854 # we might be looking at a piece of verbatim text. 855 if (len(structured_text) - end >= 6 856 and structured_text[end:end+3] == "'''"): 857 end = string.find(structured_text, "'''", end + 3) 858 if end > 0: 859 end = end + 3 860 # Add the new paragraph to the ist. 861 paragraphs.append(structured_text[begin:end]) 862 begin = end 863 continue 864 else: 865 # Loop through the string until we find the end of the 866 # text. 867 while end < len(structured_text): 868 # See if we are at the end of a paragraph. 869 match = __paragraph_regexp.match(structured_text, end) 870 if match: 871 # Add the new paragraph to the list. 872 paragraphs.append(structured_text[begin:end]) 873 # The next paragraph begins with the first 874 # matched character. 875 begin = match.end() 876 end = begin 877 break 878 else: 879 # Advance to the next character. 880 end = end + 1 881 882 # We may have stopped in the middle of a paragraph. 883 if begin != end: 884 paragraphs.append(structured_text[begin:end]) 885 886 return paragraphs
887 888
889 -def get_first_paragraph(structured_text):
890 """Return the first paragraph of 'structured_text'. 891 892 'structured_text' -- A string consisting of structured text. 893 894 returns -- A string of structured text that is the first paragraph 895 of the 'structured_text'.""" 896 897 return get_paragraphs(structured_text)[0]
898 899 ######################################################################## 900 # variables 901 ######################################################################## 902 903 # Write a regular expression for finding characters that need to be 904 # escaped as HTML entities. 905 __entity_char_regex = htmlentitydefs.entitydefs.values() 906 # We only handle single-byte characters. 907 __entity_char_regex = filter(lambda l: len(l) == 1, __entity_char_regex) 908 __entity_char_regex = "[" + string.join(__entity_char_regex, "") + "]" 909 __entity_char_regex = re.compile(__entity_char_regex) 910 911 # Generate a replacement function for special characters to HTML 912 # entities. Start by creating a map from the character to the 913 # corresponding HTML entity code. 914 __entity_char_replacement = {} 915 for entity, character in htmlentitydefs.entitydefs.items(): 916 if len(character) == 1: 917 __entity_char_replacement[character] = "&%s;" % entity 918 # Write a function for use as the regex replacement that looks up the 919 # corresponding entity for a matched character. 920 __entity_char_replacement = lambda match, \ 921 replacement_map=__entity_char_replacement: \ 922 replacement_map[match.group(0)] 923 924 # Regex matching paragraph separators. 925 __paragraph_regexp = re.compile("(?:\n *)+\n") 926 927 # Regular expression matching verbatim paragraphs and trailing 928 # whitespace. 929 _verbatim_regexp = re.compile("('''.*''')(?:(?:\n *)+\n|\n?$)", re.DOTALL) 930 931 ######################################################################## 932 # script 933 ######################################################################## 934 935 # If invoked as a script, act as a structured text processor. 936 937 if __name__ == "__main__": 938 # Parse command-line options. 939 import getopt 940 long_options = [ 941 "html", 942 "text", 943 ] 944 options, arguments = getopt.getopt(sys.argv[1:], "", long_options) 945 # Interpret them. 946 formatter = None 947 for option, option_argument in options: 948 if option == "--html": 949 formatter = HtmlFormatter() 950 elif option == "--text": 951 formatter = TextFormatter() 952 # Use a text formatter by default. 953 if formatter is None: 954 formatter = TextFormatter() 955 956 # Fire up a processor. 957 processor = StructuredTextProcessor(formatter) 958 959 # Were input files specified on the command line? 960 if len(arguments) == 0: 961 # No; read from standard input. 962 inputs = (sys.stdin, ) 963 else: 964 # Yes; open them all. 965 inputs = map(lambda file_name: open(file_name, "rt"), arguments) 966 967 # Loop over inputs. 968 for input in inputs: 969 # Read in each one, and process it. 970 processor(input.read()) 971 972 # End processing. 973 processor.End() 974 975 # All done. 976 sys.exit(0) 977 978 979 ######################################################################## 980 # Local Variables: 981 # mode: python 982 # indent-tabs-mode: nil 983 # fill-column: 72 984 # End: 985

qmtest-2.4.1/share/doc/qmtest/html/manual/string.Template-class.html0000664000076400007640000003735011122067151025051 0ustar stefanstefan string.Template
string :: Template :: Class Template
[hide private]
[frames] | no frames]

Class Template

source code

object --+
         |
        Template

A string class for supporting $-substitutions.

Nested Classes [hide private]
  __metaclass__
Instance Methods [hide private]
 
__init__(self, template)
x.__init__(...) initializes x; see x.__class__.__doc__ for signature
source code
 
_invalid(self, mo) source code
 
safe_substitute(self, *args, **kws) source code
 
substitute(self, *args, **kws) source code

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  delimiter = '$'
  idpattern = '[_a-z][_a-z0-9]*'
  pattern = re.compile(r'(?ix)\$(?:(?P<escaped>\$)|(?P<named>[_a...
Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, template)
(Constructor)

source code 

x.__init__(...) initializes x; see x.__class__.__doc__ for signature

Overrides: object.__init__
(inherited documentation)

Class Variable Details [hide private]

pattern

Value:
re.compile(r'(?ix)\$(?:(?P<escaped>\$)|(?P<named>[_a-z][_a-z0-9]*)|\{(\
?P<braced>[_a-z][_a-z0-9]*)\}|(?P<invalid>))')

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.TimeField-class.html0000664000076400007640000005171511122067146025521 0ustar stefanstefan qm.fields.TimeField
qm :: fields :: TimeField :: Class TimeField
[hide private]
[frames] | no frames]

Class TimeField

source code

object --+        
         |        
     Field --+    
             |    
  IntegerField --+
                 |
                TimeField

A field containing a date and time.

The data and time is stored as seconds since the start of the UNIX epoch, UTC (the semantics of the standard 'time' function), with one-second precision. User representations of 'TimeField' fields show one-minue precision.

Instance Methods [hide private]
 
__init__(self, name='', **properties)
Create a time field.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
FormatValueAsText(self, value, columns=72)
Return a plain text rendering of a 'value' for this field.
source code
 
FormatValueAsHtml(self, server, value, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
ParseTextValue(self, value)
Parse a value represented as a string.
source code
 
GetDefaultValue(self)
Return the default value for this field.
source code

Inherited from IntegerField: GetValueFromDomNode, MakeDomNodeForValue, Validate

Inherited from Field: GetBriefDescription, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, ParseFormValue, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', **properties)
(Constructor)

source code 

Create a time field.

The field is given a default value for this field is 'None', which corresponds to the current time when the field value is first created.

Overrides: object.__init__

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: Field.GetHelp
(inherited documentation)

FormatValueAsText(self, value, columns=72)

source code 

Return a plain text rendering of a 'value' for this field.

'columns' -- The maximum width of each line of text.

returns -- A plain-text string representing 'value'.

Overrides: Field.FormatValueAsText
(inherited documentation)

FormatValueAsHtml(self, server, value, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

Overrides: Field.FormatValueAsHtml
(inherited documentation)

ParseTextValue(self, value)

source code 

Parse a value represented as a string.

'value' -- A string representing the value.

returns -- The corresponding field value. The value returned should be processed by 'Validate' to ensure that it is valid before it is returned.

Overrides: Field.ParseTextValue
(inherited documentation)

GetDefaultValue(self)

source code 

Return the default value for this field.

Overrides: Field.GetDefaultValue
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.file_result_reader-module.html0000664000076400007640000000216411122067144030162 0ustar stefanstefan file_result_reader

Module file_result_reader


Classes

FileResultReader

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.directory_suite-pysrc.html0000664000076400007640000014102511122067161026627 0ustar stefanstefan qm.test.directory_suite
Package qm :: Package test :: Module directory_suite
[hide private]
[frames] | no frames]

Source Code for Module qm.test.directory_suite

 1  ######################################################################## 
 2  # 
 3  # File:   directory_suite.py 
 4  # Author: Mark Mitchell 
 5  # Date:   2001-10-06 
 6  # 
 7  # Contents: 
 8  #   QMTest DirectorySuite class. 
 9  # 
10  # Copyright (c) 2001 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # imports 
18  ######################################################################## 
19   
20  from qm.test.suite import * 
21   
22  ######################################################################## 
23  # classes 
24  ######################################################################## 
25   
26 -class DirectorySuite(Suite):
27 """A 'DirectorySuite' is a suite corresponding to a directory. 28 29 A 'DirectorySuite' is an implicit suite that contains all tests 30 within a given directory. The directory is given by a label, not 31 a file system directory, so a 'DirectorySuite' can work with any 32 database.""" 33
34 - def __init__(self, database, directory):
35 """Construct a new 'DirectorySuite'. 36 37 'database' -- The 'Database' instance containing this suite. 38 39 'directory' -- A label giving the directory corresponding to 40 this suite.""" 41 42 # Construct the base class. 43 super(DirectorySuite, self).__init__({}, 44 qmtest_id = directory, 45 qmtest_database = database)
46 47
48 - def GetTestIds(self):
49 """Return the tests contained in this suite. 50 51 returns -- A sequence of labels corresponding to the tests 52 contained in this suite. Tests that are contained in this suite 53 only because they are contained in a suite which is itself 54 contained in this suite are not returned.""" 55 56 return self.GetDatabase().GetTestIds(self.GetId(), scan_subdirs=0)
57 58
59 - def GetSuiteIds(self):
60 """Return the suites contained in this suite. 61 62 returns -- A sequence of labels corresponding to the suites 63 contained in this suite. Suites that are contained in this 64 suite only because they are contained in a suite which is itself 65 contained in this suite are not returned.""" 66 67 return self.GetDatabase().GetSuiteIds(self.GetId(), scan_subdirs=0)
68 69
70 - def IsImplicit(self):
71 72 return 1
73 74 ######################################################################## 75 # Local Variables: 76 # mode: python 77 # indent-tabs-mode: nil 78 # fill-column: 72 79 # End: 80

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.expectation_database-pysrc.html0000664000076400007640000005676611122067160027601 0ustar stefanstefan qm.test.expectation_database
Package qm :: Package test :: Module expectation_database
[hide private]
[frames] | no frames]

Source Code for Module qm.test.expectation_database

 1  ######################################################################## 
 2  # 
 3  # File:   expectation_database.py 
 4  # Author: Stefan Seefeld 
 5  # Date:   2006-11-05 
 6  # 
 7  # Contents: 
 8  #   QMTest ExpectationDatabase class. 
 9  # 
10  # Copyright (c) 2006 by CodeSourcery, Inc.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from qm.extension import Extension 
21  from qm.fields import PythonField 
22  from qm.test.result import Result 
23   
24  ######################################################################## 
25  # Classes 
26  ######################################################################## 
27   
28 -class ExpectationDatabase(Extension):
29 """An 'ExpectationDatabase' stores result expectations. 30 31 An 'ExpectationDatabase' provides a mechanism to store and make 32 accessible expectations for test outcomes. 33 By default, all tests are expected to pass. 34 """ 35 36 37 kind = 'expectation_database' 38 39 40 test_database = PythonField() 41 testrun_parameters = PythonField() 42 43
44 - def Lookup(self, test_id):
45 """Look up the expected outcome for the given test. 46 47 'test_id' -- test-id for which the outcome is queried. 48 49 returns -- a Result object associated with this test_id.""" 50 51 return Result(Result.TEST, test_id)
52 53
54 - def GetExpectedOutcomes(self):
55 """Return a dict object mapping test ids to expected outcomes.""" 56 57 outcomes = {} 58 if self.test_database: 59 for test_id in self.test_database.GetTestIds(): 60 outcomes[test_id] = self.Lookup(test_id).GetOutcome() 61 return outcomes
62

qmtest-2.4.1/share/doc/qmtest/html/manual/epydoc.js0000664000076400007640000002452511122067143021622 0ustar stefanstefanfunction toggle_private() { // Search for any private/public links on this page. Store // their old text in "cmd," so we will know what action to // take; and change their text to the opposite action. var cmd = "?"; var elts = document.getElementsByTagName("a"); for(var i=0; i...
"; elt.innerHTML = s; } } function toggle(id) { elt = document.getElementById(id+"-toggle"); if (elt.innerHTML == "-") collapse(id); else expand(id); return false; } function highlight(id) { var elt = document.getElementById(id+"-def"); if (elt) elt.className = "py-highlight-hdr"; var elt = document.getElementById(id+"-expanded"); if (elt) elt.className = "py-highlight"; var elt = document.getElementById(id+"-collapsed"); if (elt) elt.className = "py-highlight"; } function num_lines(s) { var n = 1; var pos = s.indexOf("\n"); while ( pos > 0) { n += 1; pos = s.indexOf("\n", pos+1); } return n; } // Collapse all blocks that mave more than `min_lines` lines. function collapse_all(min_lines) { var elts = document.getElementsByTagName("div"); for (var i=0; i 0) if (elt.id.substring(split, elt.id.length) == "-expanded") if (num_lines(elt.innerHTML) > min_lines) collapse(elt.id.substring(0, split)); } } function expandto(href) { var start = href.indexOf("#")+1; if (start != 0 && start != href.length) { if (href.substring(start, href.length) != "-") { collapse_all(4); pos = href.indexOf(".", start); while (pos != -1) { var id = href.substring(start, pos); expand(id); pos = href.indexOf(".", pos+1); } var id = href.substring(start, href.length); expand(id); highlight(id); } } } function kill_doclink(id) { var parent = document.getElementById(id); parent.removeChild(parent.childNodes.item(0)); } function auto_kill_doclink(ev) { if (!ev) var ev = window.event; if (!this.contains(ev.toElement)) { var parent = document.getElementById(this.parentID); parent.removeChild(parent.childNodes.item(0)); } } function doclink(id, name, targets_id) { var elt = document.getElementById(id); // If we already opened the box, then destroy it. // (This case should never occur, but leave it in just in case.) if (elt.childNodes.length > 1) { elt.removeChild(elt.childNodes.item(0)); } else { // The outer box: relative + inline positioning. var box1 = document.createElement("div"); box1.style.position = "relative"; box1.style.display = "inline"; box1.style.top = 0; box1.style.left = 0; // A shadow for fun var shadow = document.createElement("div"); shadow.style.position = "absolute"; shadow.style.left = "-1.3em"; shadow.style.top = "-1.3em"; shadow.style.background = "#404040"; // The inner box: absolute positioning. var box2 = document.createElement("div"); box2.style.position = "relative"; box2.style.border = "1px solid #a0a0a0"; box2.style.left = "-.2em"; box2.style.top = "-.2em"; box2.style.background = "white"; box2.style.padding = ".3em .4em .3em .4em"; box2.style.fontStyle = "normal"; box2.onmouseout=auto_kill_doclink; box2.parentID = id; // Get the targets var targets_elt = document.getElementById(targets_id); var targets = targets_elt.getAttribute("targets"); var links = ""; target_list = targets.split(","); for (var i=0; i" + target[0] + ""; } // Put it all together. elt.insertBefore(box1, elt.childNodes.item(0)); //box1.appendChild(box2); box1.appendChild(shadow); shadow.appendChild(box2); box2.innerHTML = "Which "+name+" do you want to see documentation for?" + ""; } return false; } function get_anchor() { var href = location.href; var start = href.indexOf("#")+1; if ((start != 0) && (start != href.length)) return href.substring(start, href.length); } function redirect_url(dottedName) { // Scan through each element of the "pages" list, and check // if "name" matches with any of them. for (var i=0; i-m" or "-c"; // extract the portion & compare it to dottedName. var pagename = pages[i].substring(0, pages[i].length-2); if (pagename == dottedName.substring(0,pagename.length)) { // We've found a page that matches `dottedName`; // construct its URL, using leftover `dottedName` // content to form an anchor. var pagetype = pages[i].charAt(pages[i].length-1); var url = pagename + ((pagetype=="m")?"-module.html": "-class.html"); if (dottedName.length > pagename.length) url += "#" + dottedName.substring(pagename.length+1, dottedName.length); return url; } } } qmtest-2.4.1/share/doc/qmtest/html/manual/qm.label.Label-class.html0000664000076400007640000004223011122067146024477 0ustar stefanstefan qm.label.Label
Package qm :: Module label :: Class Label
[hide private]
[frames] | no frames]

Class Label

source code

Known Subclasses:

A 'Label' identifies an entity.

A 'Label' is a generalization of a filename. Like filenames, labels consist of one or more directories followed by a basename. However, the format used for a label need not be the same as that used by filenames.

Each label class defines a separator character to take the place of the '/' character used by many file systems.

All labels are relative labels; no label may begin with a separator character.

Instance Methods [hide private]
 
__init__(self, label)
Construct a new 'Label'.
source code
 
Join(self, *labels)
Combine this label and the 'labels' into a single label.
source code
 
Split(self)
Split the label into a pair '(directory, basename)'.
source code
 
SplitLeft(self)
Split the label into a pair '(parent, subpath)'.
source code
 
Basename(self)
Return the basename for the label.
source code
 
Dirname(self)
Return the directory name for the 'label'.
source code
 
IsValid(self, label, is_component)
Returns true if 'label' is valid.
source code
 
__str__(self)
Return the string form of this label.
source code
Method Details [hide private]

__init__(self, label)
(Constructor)

source code 

Construct a new 'Label'.

'label' -- A string giving the value of the label.

Join(self, *labels)

source code 

Combine this label and the 'labels' into a single label.

'labels' -- A sequence of strings giving the components of the new label. All but the last are taken as directory names; the last is treated as a basename.

Split(self)

source code 

Split the label into a pair '(directory, basename)'.

returns -- A pair '(directory, basename)', each of which is a label.

It is always true that 'directory.join(basename)' will return a label equivalent to the original label.

SplitLeft(self)

source code 

Split the label into a pair '(parent, subpath)'. This is the same operation as Split, except the split occurs at the leftmost separator, not the rightmost.

returns -- A pair '(directory, basename)', each of which is a label.

It is always true that 'directory.join(basename)' will return a label equivalent to the original label.

Basename(self)

source code 

Return the basename for the label.

returns -- A string giving the basename for the label. The value returned for 'l.basename()' is always the same as 'l.split()[1]'.

Dirname(self)

source code 

Return the directory name for the 'label'.

returns -- A string giving the directory name for the 'label'. The value returned for 'l.dirname()' is always the same as 'l.split()[0]'.

IsValid(self, label, is_component)

source code 

Returns true if 'label' is valid.

'label' -- The string being tested for validity.

'is_component' -- True if the string being tested is just a single component of a label path.

returns -- True if 'label' is not valid.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.LoadResultsPage-class.html0000664000076400007640000003550311122067151027747 0ustar stefanstefan qm.test.web.web.LoadResultsPage
Package qm :: Package test :: Package web :: Module web :: Class LoadResultsPage
[hide private]
[frames] | no frames]

Class LoadResultsPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      LoadResultsPage

DTML page for uploading a context.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server)
Construct a new 'LoadContextPage'.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]
  title = "Load Results"
The title for the page.
  heading = "Load results from a file."
The heading printed across the top of the page.
  prompt = "The file from which to load the results." ""
The prompt for the file name.
  submit_url = "submit-results"
The URL to which the file should be submitted.

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server)
(Constructor)

source code 

Construct a new 'LoadContextPage'.

'server' -- The 'QMTestServer' creating this page.

Overrides: web.DtmlPage.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.IntegerField-class.html0000664000076400007640000006272611122067146026224 0ustar stefanstefan qm.fields.IntegerField
qm :: fields :: IntegerField :: Class IntegerField
[hide private]
[frames] | no frames]

Class IntegerField

source code

object --+    
         |    
     Field --+
             |
            IntegerField
Known Subclasses:

An 'IntegerField' stores an 'int' or 'long' object.

Instance Methods [hide private]
 
__init__(self, name='', default_value=0, **properties)
Construct a new 'IntegerField'.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
FormatValueAsText(self, value, columns=72)
Return a plain text rendering of a 'value' for this field.
source code
 
FormatValueAsHtml(self, server, value, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
MakeDomNodeForValue(self, value, document)
Generate a DOM element node for a value of this field.
source code
 
Validate(self, value)
Validate a field value.
source code
 
ParseTextValue(self, value)
Parse a value represented as a string.
source code
 
GetValueFromDomNode(self, node, attachment_store)
Return a value for this field represented by DOM 'node'.
source code

Inherited from Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, ParseFormValue, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', default_value=0, **properties)
(Constructor)

source code 

Construct a new 'IntegerField'.

'name' -- As for 'Field.__init__'.

'default_value' -- As for 'Field.__init__'.

'properties' -- Other keyword arguments for 'Field.__init__'.

Overrides: object.__init__

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: Field.GetHelp
(inherited documentation)

FormatValueAsText(self, value, columns=72)

source code 

Return a plain text rendering of a 'value' for this field.

'columns' -- The maximum width of each line of text.

returns -- A plain-text string representing 'value'.

Overrides: Field.FormatValueAsText
(inherited documentation)

FormatValueAsHtml(self, server, value, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

Overrides: Field.FormatValueAsHtml
(inherited documentation)

MakeDomNodeForValue(self, value, document)

source code 

Generate a DOM element node for a value of this field.

'value' -- The value to represent.

'document' -- The containing DOM document node.

Overrides: Field.MakeDomNodeForValue
(inherited documentation)

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

Overrides: Field.Validate
(inherited documentation)

ParseTextValue(self, value)

source code 

Parse a value represented as a string.

'value' -- A string representing the value.

returns -- The corresponding field value. The value returned should be processed by 'Validate' to ensure that it is valid before it is returned.

Overrides: Field.ParseTextValue
(inherited documentation)

GetValueFromDomNode(self, node, attachment_store)

source code 

Return a value for this field represented by DOM 'node'.

This method does not validate the value for this particular instance; it only makes sure the node is well-formed, and returns a value of the correct Python type.

'node' -- The DOM node that is being evaluated.

'attachment_store' -- For attachments, the store that should be used.

If the 'node' is incorrectly formed, this method should raise an exception.

Overrides: Field.GetValueFromDomNode
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.serial_target-pysrc.html0000664000076400007640000011515211122067162027676 0ustar stefanstefan qm.test.classes.serial_target
Package qm :: Package test :: Package classes :: Module serial_target
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.serial_target

 1  ######################################################################## 
 2  # 
 3  # File:   serial_target.py 
 4  # Author: Mark Mitchell 
 5  # Date:   12/19/2001 
 6  # 
 7  # Contents: 
 8  #   SerialTarget 
 9  # 
10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  ######################################################################## 
13   
14  ######################################################################## 
15  # Imports 
16  ######################################################################## 
17   
18  from   qm.test.target import Target 
19  from   qm.temporary_directory import TemporaryDirectory 
20   
21  ######################################################################## 
22  # Classes 
23  ######################################################################## 
24   
25 -class SerialTarget(Target):
26 """A target that runs tests in serial on the local machine.""" 27
28 - def __init__(self, database, properties):
29 30 super(SerialTarget, self).__init__(database, properties) 31 self.__temporary_directory = TemporaryDirectory()
32 33
34 - def IsIdle(self):
35 """Return true if the target is idle. 36 37 returns -- True if the target is idle. If the target is idle, 38 additional tasks may be assigned to it.""" 39 40 # The target is always idle when this method is called since 41 # whenever it asked to perform a task it blocks the caller. 42 return 1
43 44
45 - def _GetTemporaryDirectory(self):
46 47 return self.__temporary_directory.GetPath()
48

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.test.Test.TestField-class.html0000664000076400007640000002763011122067151027142 0ustar stefanstefan qm.test.test.Test.TestField
Package qm :: Package test :: Module test :: Class Test :: Class TestField
[hide private]
[frames] | no frames]

Class TestField

source code

  object --+            
           |            
fields.Field --+        
               |        
fields.TextField --+    
                   |    
  fields.ChoiceField --+
                       |
                      Test.TestField

A 'TestField' contains the name of a test.

The exact format of the name depends on the test database in use.

Instance Methods [hide private]
 
GetItems(self)
Return the options from which to choose.
source code

Inherited from fields.ChoiceField: FormatValueAsHtml, Validate

Inherited from fields.TextField: FormatValueAsText, GetHelp, GetValueFromDomNode, MakeDomNodeForValue, ParseFormValue, ParseTextValue, __init__

Inherited from fields.Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from fields.Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

GetItems(self)

source code 

Return the options from which to choose.

returns -- A sequence of strings, each of which will be presented as a choice for the user.

Overrides: fields.ChoiceField.GetItems
(inherited documentation)

././@LongLink0000000000000000000000000000014700000000000011567 Lustar rootrootqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test.CompiledResource-class.htmlqmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.compilation_test.CompiledResource-class.ht0000664000076400007640000004745111122067147033316 0ustar stefanstefan qm.test.classes.compilation_test.CompiledResource
Package qm :: Package test :: Package classes :: Module compilation_test :: Class CompiledResource
[hide private]
[frames] | no frames]

Class CompiledResource

source code

         object --+            
                  |            
extension.Extension --+        
                      |        
      runnable.Runnable --+    
                          |    
          resource.Resource --+
                              |
                             CompiledResource

A CompiledResource compiles an executable.

Nested Classes [hide private]

Inherited from runnable.Runnable: ResourceField

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
SetUp(self, context, result)
Set up the resource.
source code
 
CleanUp(self, result)
Clean up the resource.
source code

Inherited from runnable.Runnable: GetAttachments, GetDatabase, GetId, __init__

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  options = SetField(TextField(description= "Resource-specific o...
  source_files = SetField(TextField(description= "Source files t...
  executable = TextField(description= "The name of the executabl...

Inherited from resource.Resource: kind

Inherited from runnable.Runnable: EXTRA_DATABASE, EXTRA_ID, RESOURCE_FIELD_ID, arguments, resources

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

SetUp(self, context, result)

source code 

Set up the resource.

'context' -- A 'Context' giving run-time parameters to the resource. The resource may place additional variables into the 'context'; these variables will be visible to tests that depend on the resource.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes must override this method.

Overrides: resource.Resource.SetUp
(inherited documentation)

CleanUp(self, result)

source code 

Clean up the resource.

'result' -- A 'Result' object. The outcome will be 'Result.PASS' when this method is called. The 'result' may be modified by this method to indicate outcomes other than 'Result.PASS' or to add annotations.

This method should not return a value.

Derived classes may override this method.

Overrides: resource.Resource.CleanUp
(inherited documentation)

Class Variable Details [hide private]

options

Value:
SetField(TextField(description= "Resource-specific options to pass to \
the compiler."))

source_files

Value:
SetField(TextField(description= "Source files to be compiled."))

executable

Value:
TextField(description= "The name of the executable to be compiled.")

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.explicit_suite-pysrc.html0000664000076400007640000007325411122067156030114 0ustar stefanstefan qm.test.classes.explicit_suite
Package qm :: Package test :: Package classes :: Module explicit_suite
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.explicit_suite

 1  ######################################################################## 
 2  # 
 3  # File:   suite.py 
 4  # Author: Mark Mitchell 
 5  # Date:   1/02/2004 
 6  # 
 7  # Contents: 
 8  #   QMTest ExplicitSuite class 
 9  # 
10  # Copyright (c) 2004 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # Imports 
18  ######################################################################## 
19   
20  from   qm.fields import BooleanField, SetField, TextField 
21  import qm.test.suite 
22   
23  ######################################################################## 
24  # Classes 
25  ######################################################################## 
26   
27 -class ExplicitSuite(qm.test.suite.Suite):
28 """An 'ExplicitSuite' stores all of the test and suite ids explicitly.""" 29 30 arguments = [ 31 SetField( 32 TextField( 33 name = "test_ids", 34 title = "Test Names", 35 description = """The the tests contained in this suite.""")), 36 SetField( 37 TextField( 38 name = "suite_ids", 39 title = "Suite Names", 40 description = """The the suites contained in this suite.""")), 41 BooleanField(name = "is_implicit", 42 title = "Implicit?", 43 description = """\ 44 True if this test is implicitly generated by QMTest.""", 45 default_value = "false"), 46 ] 47
48 - def IsImplicit(self):
49 50 return self.is_implicit == "true"
51 52
53 - def GetTestIds(self):
54 55 return self.test_ids
56 57
58 - def GetSuiteIds(self):
59 60 return self.suite_ids
61

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.classes.compiler_table-module.html0000664000076400007640000000215211122067144030735 0ustar stefanstefan compiler_table

Module compiler_table


Classes

CompilerTable

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.external.DocumentTemplate.DT_UI-module.html0000664000076400007640000000233411122067144031342 0ustar stefanstefan DT_UI

Module DT_UI


Variables

FactoryDefaultString
__doc__

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.target.Target.__ResourceSetUpException-class.html0000664000076400007640000002204011122067150033007 0ustar stefanstefan qm.test.target.Target.__ResourceSetUpException
Package qm :: Package test :: Module target :: Class Target :: Class __ResourceSetUpException
[hide private]
[frames] | no frames]

Class __ResourceSetUpException

source code

              object --+        
                       |        
exceptions.BaseException --+    
                           |    
        exceptions.Exception --+
                               |
                              Target.__ResourceSetUpException

An exception indicating that a resource could not be set up.

Instance Methods [hide private]
 
__init__(self, resource)
Construct a new 'ResourceSetUpException'.
source code

Inherited from exceptions.Exception: __new__

Inherited from exceptions.BaseException: __delattr__, __getattribute__, __getitem__, __getslice__, __reduce__, __repr__, __setattr__, __setstate__, __str__

Inherited from object: __hash__, __reduce_ex__

Properties [hide private]

Inherited from exceptions.BaseException: args, message

Inherited from object: __class__

Method Details [hide private]

__init__(self, resource)
(Constructor)

source code 

Construct a new 'ResourceSetUpException'.

'resource' -- The name of the resoure that could not be set up.

Overrides: object.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.command_thread-module.html0000664000076400007640000000214211122067144027264 0ustar stefanstefan command_thread

Module command_thread


Classes

CommandThread

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-L.html0000664000076400007640000003572711122067144024316 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

L



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_If.Else-class.html0000664000076400007640000001464311122067146031317 0ustar stefanstefan qm.external.DocumentTemplate.DT_If.Else
Package qm :: Package external :: Package DocumentTemplate :: Module DT_If :: Class Else
[hide private]
[frames] | no frames]

Class Else

source code

Unless --+
         |
        Else

Instance Methods [hide private]

Inherited from Unless: __init__

Class Variables [hide private]
  name = 'else'

Inherited from Unless: blockContinuations

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.dist-module.html0000664000076400007640000000170111122067144024304 0ustar stefanstefan dist

Module dist



[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.text_result_stream-pysrc.html0000664000076400007640000054441511122067160031014 0ustar stefanstefan qm.test.classes.text_result_stream
Package qm :: Package test :: Package classes :: Module text_result_stream
[hide private]
[frames] | no frames]

Source Code for Module qm.test.classes.text_result_stream

  1  ######################################################################## 
  2  # 
  3  # File:   test_result_stream.py 
  4  # Author: Mark Mitchell 
  5  # Date:   2001-10-10 
  6  # 
  7  # Contents: 
  8  #   QMTest TextResultStream class. 
  9  # 
 10  # Copyright (c) 2001, 2002, 2003 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # imports 
 18  ######################################################################## 
 19   
 20  import qm.common 
 21  import qm.fields 
 22  from   qm.test.base import * 
 23  from   qm.test.result import * 
 24  from   qm.test.file_result_stream import FileResultStream 
 25   
 26  ######################################################################## 
 27  # classes 
 28  ######################################################################## 
 29   
30 -class TextResultStream(FileResultStream):
31 """A 'TextResultStream' displays test results textually. 32 33 A 'TextResultStream' displays information textually, in human 34 readable form. This 'ResultStream' is used when QMTest is run 35 without a graphical user interface.""" 36 37 arguments = [ 38 qm.fields.EnumerationField( 39 name = "format", 40 title = "Format", 41 description = """The output format used by this result stream. 42 43 There are three sections to the output: 44 45 (S) Summary statistics. 46 47 (I) Individual test-by-test results. 48 49 (U) Individual test-by-test results for tests with unexpected 50 outcomes. 51 52 For each of the sections of individual test-by-test results, the 53 results can be shown either in one of three modes: 54 55 (A) Show all annotations. 56 57 (N) Show no annotations. 58 59 (U) Show annotations only if the test has an unexpected outcome. 60 61 In the "brief" format, results for all tests are shown as 62 they execute, with unexpected results displayed in full 63 detail, followed by a list of all the tests with 64 unexpected results in full detail, followed by the summary 65 information. This format is useful for interactive use: 66 the user can see that the tests are running as they go, 67 can attempt to fix failures while letting the remainder of 68 the tests run, and can easily see the summary of the 69 results later if the window in which the run is occurring 70 is left unattended. 71 72 In the "batch" format, statistics are displayed first 73 followed by full results for tests with unexpected 74 outcomes. The batch format is useful when QMTest is run 75 in batch mode, such as from an overnight job. The first 76 few lines of the results (often presented by email) give 77 an overview of the results; the remainder of the file 78 gives details about any tests with unexpected outcomes. 79 80 The "full" format is like "brief" except that all 81 annotations are shown for tests as they are run. 82 83 In the "stats" format only the summary statistics are 84 displayed.""", 85 enumerals = ["brief", "batch", "full", "stats"]), 86 qm.fields.TextField( 87 name = "statistics_format", 88 title = "Statistics Format", 89 verbatim = "true", 90 multiline = "true", 91 description = """The format string used to display statistics. 92 93 The format string is an ordinary Python format string. 94 The following fill-ins are available: 95 96 'TOTAL' -- The total number of tests. 97 98 'EXPECTED' -- The total number of tests that had an 99 expected outcome. 100 101 'EXPECTED_PERCENT' -- The percentage of tests with 102 expected outcomes. 103 104 'UNEXPECTED' -- The total number of tests that had an 105 unexpected outcome. 106 107 For each outcome 'O', there are additional fill-ins: 108 109 'O' -- The total number of tests with outcome 'O'. 110 111 'O_PERCENT' -- The percentage of tests with outcome 'O' to 112 total tests, as a floating point value. 113 114 'O_UNEXPECTED' -- The total number of tests with an 115 unexpected outcome of 'O'. 116 117 'O_UNEXEPECTED_PERCENT' -- The ratio of tests without an 118 unexpected outcome of 'O' to total tests, as a floating 119 point value."""), 120 ] 121
122 - def __init__(self, arguments = None, **args):
123 """Construct a 'TextResultStream'. 124 125 'args' -- As for 'Extension.__init__'.""" 126 127 # Initialize the base class. 128 super(TextResultStream, self).__init__(arguments, **args) 129 130 # Pick a default format. 131 if not self.format: 132 self.format = "batch" 133 try: 134 if self.file.isatty(): 135 self.format = "brief" 136 except: 137 pass 138 139 self.__first_test = 1 140 # Keep track of tests and resources that had unexpected outcomes. 141 self.__unexpected_test_results = [] 142 self.__unexpected_resource_results = [] 143 # And how many tests were run. 144 self.__num_tests = 0 145 # And how many tests there are with each outcome. 146 self.__outcome_counts = {} 147 for o in Result.outcomes: 148 self.__outcome_counts[o] = 0 149 # And how many unexpected tests there are with each outcome. 150 self.__unexpected_outcome_counts = {} 151 for o in Result.outcomes: 152 self.__unexpected_outcome_counts[o] = 0
153 154
155 - def WriteResult(self, result):
156 """Output a test or resource result. 157 158 'result' -- A 'Result'.""" 159 160 # Record the results as they are received. 161 if result.GetKind() == Result.TEST: 162 # Remember how many tests we have processed. 163 self.__num_tests += 1 164 # Increment the outcome count. 165 outcome = result.GetOutcome() 166 self.__outcome_counts[outcome] += 1 167 # Remember tests with unexpected results so that we can 168 # display them at the end of the run. 169 test_id = result.GetId() 170 expected_outcome = self._GetExpectedOutcome(result.GetId()) 171 if self.format != "stats" and outcome != expected_outcome: 172 self.__unexpected_outcome_counts[outcome] += 1 173 self.__unexpected_test_results.append(result) 174 else: 175 if (self.format != "stats" 176 and result.GetOutcome() != result.PASS): 177 self.__unexpected_resource_results.append(result) 178 179 # In some modes, no results are displayed as the tests are run. 180 if self.format == "batch" or self.format == "stats": 181 return 182 183 # Display a heading before the first result. 184 if self.__first_test: 185 self._DisplayHeading("TEST RESULTS") 186 self.__first_test = 0 187 188 # Display the result. 189 self._DisplayResult(result, self.format) 190 191 # Display annotations associated with the test. 192 if (self.format == "full" 193 or (self.format == "brief" 194 and result.GetOutcome() != Result.PASS)): 195 self._DisplayAnnotations(result)
196 197
198 - def Summarize(self):
199 """Output summary information about the results. 200 201 When this method is called, the test run is complete. Summary 202 information should be displayed for the user, if appropriate. 203 Any finalization, such as the closing of open files, should 204 also be performed at this point.""" 205 206 if self.format == "batch": 207 self._DisplayStatistics() 208 209 # Show results for tests with unexpected outcomes. 210 if self.format in ("full", "brief", "batch"): 211 compare_ids = lambda r1, r2: cmp(r1.GetId(), r2.GetId()) 212 213 # Sort test results by ID. 214 self.__unexpected_test_results.sort(compare_ids) 215 # Print individual test results. 216 if self.expected_outcomes: 217 self._DisplayHeading("TESTS WITH UNEXPECTED OUTCOMES") 218 else: 219 self._DisplayHeading("TESTS THAT DID NOT PASS") 220 self._SummarizeResults(self.__unexpected_test_results) 221 222 if self.__unexpected_resource_results: 223 # Sort resource results by ID. 224 self.__unexpected_resource_results.sort(compare_ids) 225 # Print individual resource results. 226 self._DisplayHeading("RESOURCES THAT DID NOT PASS") 227 self._SummarizeResults(self.__unexpected_resource_results) 228 229 if self.format != "batch": 230 self._DisplayStatistics() 231 232 # Invoke the base class method. 233 super(TextResultStream, self).Summarize()
234 235
236 - def _DisplayStatistics(self):
237 """Write out statistical information about the results. 238 239 Write out statistical information about the results.""" 240 241 # Summarize the test statistics. 242 if self.statistics_format: 243 self._FormatStatistics(self.statistics_format) 244 elif self.expected_outcomes: 245 self._SummarizeRelativeTestStats() 246 else: 247 self._SummarizeTestStats()
248 249
250 - def _SummarizeTestStats(self):
251 """Generate statistics about the overall results.""" 252 253 # Print a header. 254 self.file.write("\n") 255 self._DisplayHeading("STATISTICS") 256 257 # Build the format string. If there are no tests we do not 258 # provide any output. 259 if self.__num_tests != 0: 260 # Indicate the total number of tests. 261 format = " %(TOTAL)6d tests total\n" 262 # Include a line for each outcome. 263 for o in Result.outcomes: 264 if self.__outcome_counts[o] != 0: 265 format += (" %%(%s)6d (%%(%s)3.0f%%%%) tests %s\n" 266 % (o, o + "_PERCENT", o)) 267 format += "\n" 268 else: 269 format = "" 270 271 self._FormatStatistics(format)
272 273
275 """Generate statistics showing results relative to expectations.""" 276 277 # Print a header. 278 self.file.write("\n") 279 self._DisplayHeading("STATISTICS") 280 281 # Build the format string. If there are no tests we do not 282 # provide any output. 283 if self.__num_tests != 0: 284 # Indicate the total number of tests. 285 format = (" %(EXPECTED)6d (%(EXPECTED_PERCENT)3.0f%%) " 286 "tests as expected\n") 287 # Include a line for each outcome. 288 for o in Result.outcomes: 289 if self.__unexpected_outcome_counts[o] != 0: 290 format += (" %%(%s)6d (%%(%s)3.0f%%%%) tests " 291 "unexpected %s\n" 292 % (o + "_UNEXPECTED", 293 o + "_UNEXPECTED_PERCENT", 294 o)) 295 format += "\n" 296 else: 297 format = "" 298 299 self._FormatStatistics(format)
300 301
302 - def _FormatStatistics(self, format):
303 """Output statistical information. 304 305 'format' -- A format string with (optional) fill-ins 306 corresponding to statistical information. 307 308 The formatted string is written to the result file.""" 309 310 # Build the dictionary of format fill-ins. 311 num_tests = self.__num_tests 312 unexpected = len(self.__unexpected_test_results) 313 expected = num_tests - unexpected 314 values = { "TOTAL" : num_tests, 315 "EXPECTED" : expected, 316 "UNEXPECTED" : unexpected } 317 if num_tests: 318 values["EXPECTED_PERCENT"] = (100. * expected) / num_tests 319 else: 320 values["EXPECTED_PERCENT"] = 0.0 321 for o in Result.outcomes: 322 count = self.__outcome_counts[o] 323 values[o] = count 324 if num_tests: 325 values[o + "_PERCENT"] = (100. * count) / num_tests 326 else: 327 values[o + "_PERCENT"] = 0.0 328 count = self.__unexpected_outcome_counts[o] 329 values[o + "_UNEXPECTED"] = count 330 if num_tests: 331 values[o + "_UNEXPECTED_PERCENT"] = (100. * count) / num_tests 332 else: 333 values[o + "_UNEXPECTED_PERCENT"] = 0.0 334 335 self.file.write(format % values)
336 337
338 - def _SummarizeResults(self, results):
339 """Summarize each of the results. 340 341 'results' -- The sequence of 'Result' objects to summarize.""" 342 343 if len(results) == 0: 344 self.file.write(" None.\n\n") 345 return 346 347 # Generate them. 348 for result in results: 349 self._DisplayResult(result, self.format) 350 if self.format == "batch": 351 self._DisplayAnnotations(result)
352 353
354 - def _DisplayResult(self, result, format):
355 """Display 'result'. 356 357 'result' -- The 'Result' of a test or resource execution. 358 359 'format' -- The format to use when displaying results.""" 360 361 id_ = result.GetId() 362 kind = result.GetKind() 363 outcome = result.GetOutcome() 364 365 # Print the ID and outcome. 366 if self.expected_outcomes: 367 # If expected outcomes were specified, print the expected 368 # outcome too. 369 expected_outcome = \ 370 self.expected_outcomes.get(id_, Result.PASS) 371 if (outcome == Result.PASS 372 and expected_outcome == Result.FAIL): 373 self._WriteOutcome(id_, kind, "XPASS") 374 elif (outcome == Result.FAIL 375 and expected_outcome == Result.FAIL): 376 self._WriteOutcome(id_, kind, "XFAIL") 377 elif outcome != expected_outcome: 378 self._WriteOutcome(id_, kind, outcome, expected_outcome) 379 else: 380 self._WriteOutcome(id_, kind, outcome) 381 else: 382 self._WriteOutcome(id_, kind, outcome) 383 384 # Print the cause of the failure. 385 cause = result.GetCause() 386 if cause: 387 cause = qm.common.html_to_text(cause) 388 for l in cause.splitlines(): 389 self.file.write(" " + l + "\n") 390 391 self.file.write('\n')
392 393
394 - def _DisplayAnnotations(self, result):
395 """Display the annotations associated with 'result'. 396 397 'result' -- The 'Result' to dispay.""" 398 399 keys = result.keys() 400 keys.sort() 401 for name in keys: 402 # The CAUSE property has already been displayed." 403 if name == Result.CAUSE: 404 continue 405 # Add an item to the list 406 self.file.write(" %s:\n" % name) 407 408 # Convert the HTML to text. 409 text = qm.common.html_to_text(result[name]) 410 411 # Write out the text. 412 for l in text.splitlines(): 413 self.file.write(" " + l + "\n") 414 self.file.write("\n")
415 416
417 - def _WriteOutcome(self, name, kind, outcome, expected_outcome=None):
418 """Write a line indicating the outcome of a test or resource. 419 420 'name' -- The name of the test or resource. 421 422 'kind' -- The kind of result being displayed. 423 424 'outcome' -- A string giving the outcome. 425 426 'expected_outcome' -- If not 'None', the expected outcome.""" 427 428 if kind == Result.RESOURCE_SETUP: 429 name = "Setup " + name 430 elif kind == Result.RESOURCE_CLEANUP: 431 name = "Cleanup " + name 432 433 if expected_outcome: 434 self.file.write(" %-46s: %-8s, expected %-8s\n" 435 % (name, outcome, expected_outcome)) 436 else: 437 self.file.write(" %-46s: %-8s\n" % (name, outcome))
438 439
440 - def _DisplayHeading(self, heading):
441 """Display 'heading'. 442 443 'heading' -- The string to use as a heading for the next 444 section of the report.""" 445 446 self.file.write("--- %s %s\n\n" % 447 (heading, "-" * (73 - len(heading))))
448

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.external.DocumentTemplate.DT_Var-module.html0000664000076400007640000010512211122067145030772 0ustar stefanstefan qm.external.DocumentTemplate.DT_Var
Package qm :: Package external :: Package DocumentTemplate :: Module DT_Var
[hide private]
[frames] | no frames]

Module DT_Var

source code

Variable insertion parameters

    When inserting variables, parameters may be specified to
    control how the data will be formatted.  In HTML source, the
    'fmt' parameter is used to specify a C-style or custom format
    to be used when inserting an object.  In EPFS source, the 'fmt'
    parameter is only used for custom formats, a C-style format is
    specified after the closing parenthesis.

    Custom formats

       A custom format is used when outputing user-defined
       objects.  The value of a custom format is a method name to
       be invoked on the object being inserted.  The method should
       return an object that, when converted to a string, yields
       the desired text.  For example, the DTML code::

          <dtml-var date fmt=DayOfWeek>

       Inserts the result of calling the method 'DayOfWeek' of the
       object bound to the variable 'date', with no arguments.

       In addition to object methods, serveral additional custom
       formats are available:

           'whole-dollars' -- Show a numeric value with a dollar symbol.

           'dollars-and-cents' -- Show a numeric value with a dollar
             symbol and two decimal places.

           'collection-length' -- Get the length of a collection of objects.

       Note that when using the EPFS source format, both a
       C-style and a custom format may be provided.  In this case,
       the C-Style format is applied to the result of calling
       the custom formatting method.

    Null values and missing variables

       In some applications, and especially in database applications,
       data variables may alternate between "good" and "null" or
       "missing" values.  A format that is used for good values may be
       inappropriate for null values.  For this reason, the 'null'
       parameter can be used to specify text to be used for null
       values.  Null values are defined as values that:

         - Cannot be formatted with the specified format, and

         - Are either the special Python value 'None' or
           are false and yield an empty string when converted to
           a string.

       For example, when showing a monitary value retrieved from a
       database that is either a number or a missing value, the
       following variable insertion might be used::

           <dtml-var cost fmt="$%.2d" null='n/a'>

       Missing values are providing for variables which are not
       present in the name space, rather than raising an NameError,
       you could do this:

           <dtml-var cost missing=0>

       and in this case, if cost was missing, it would be set to 0.
       In the case where you want to deal with both at the same time,
       you can use 'default':

           <dtml-var description default=''>

       In this case, it would use '' if the value was null or if the
       variable was missing.

    String manipulation

       A number of special attributes are provided to transform the
       value after formatting has been applied.  These parameters
       are supplied without arguments.

       'lower' --  cause all upper-case letters to be converted to lower case.

       'upper' --  cause all upper-case letters to be converted to lower case.

       'capitalize' -- cause the first character of the inserted value
       to be converted to upper case.

       'spacify' -- cause underscores in the inserted value to be
       converted to spaces.

       'thousands_commas' -- cause commas to be inserted every three
       digits to the left of a decimal point in values containing
       numbers.  For example, the value, "12000 widgets" becomes
       "12,000 widgets".

       'html_quote' -- convert characters that have special meaning
       in HTML to HTML character entities.

       'url_quote' -- convert characters that have special meaning
       in URLS to HTML character entities using decimal values.

       'url_quote_plus' -- like url_quote but also replace blank
       space characters with '+'. This is needed for building
       query strings in some cases.

       'sql_quote' -- Convert single quotes to pairs of single
       quotes. This is needed to safely include values in
       Standard Query Language (SQL) strings.

       'newline_to_br' -- Convert newlines and carriage-return and
       newline combinations to break tags.

       'url' -- Get the absolute URL of the object by calling it's
       'absolute_url' method, if it has one.

    Truncation

       The attributes 'size' and 'etc'  can be used to truncate long
       strings.  If the 'size' attribute is specified, the string to
       be inserted is truncated at the given length.  If a space
       occurs in the second half of the truncated string, then the
       string is further truncated to the right-most space.  After
       truncation, the value given for the 'etc' attribute is added to
       the string.  If the 'etc' attribute is not provided, then '...'
       is used.  For example, if the value of spam is
       '"blah blah blah blah"', then the tag       
       '<!--#var spam size=10-->' inserts '"blah blah ..."'.


Evaluating expressions without rendering results

   A 'call' tag is provided for evaluating named objects or expressions
   without rendering the result.


Version: 1069

Classes [hide private]
  Var
  Call
  Comment
Comments
Functions [hide private]
 
url_quote(v, name='(Unknown name)', md={}) source code
 
url_quote_plus(v, name='(Unknown name)', md={}) source code
 
url_unquote(v, name='(Unknown name)', md={}) source code
 
url_unquote_plus(v, name='(Unknown name)', md={}) source code
 
newline_to_br(v, name='(Unknown name)', md={}) source code
 
whole_dollars(v, name='(Unknown name)', md={}) source code
 
dollars_and_cents(v, name='(Unknown name)', md={}) source code
 
thousands_commas(v, name='(Unknown name)', md={}, thou=<built-in method search of _sre.SRE_Pattern object at 0x7f00bc...) source code
 
whole_dollars_with_commas(v, name='(Unknown name)', md={}) source code
 
dollars_and_cents_with_commas(v, name='(Unknown name)', md={}) source code
 
len_format(v, name='(Unknown name)', md={}) source code
 
len_comma(v, name='(Unknown name)', md={}) source code
 
structured_text(v, name='(Unknown name)', md={}) source code
 
sql_quote(v, name='(Unknown name)', md={})
Quote single quotes in a string by doubling them.
source code
 
spacify(val) source code
Variables [hide private]
  __doc__ = '''Variable insertion paramet...
  __rcs_id__ = '$Id: DT_Var.py 1069 2008-11-13 21:55:43Z stefan $'
  StructuredText = None
  special_formats = {'whole-dollars': whole_dollars, 'dollars-an...
  modifiers = map(lambda f:(f.__name__, f), modifiers)
Function Details [hide private]

sql_quote(v, name='(Unknown name)', md={})

source code 

Quote single quotes in a string by doubling them.

This is needed to securely insert values into sql string literals in templates that generate sql.


Variables Details [hide private]

__doc__

Value:
'''Variable insertion parameters

    When inserting variables, parameters may be specified to
    control how the data will be formatted.  In HTML source, the
    'fmt' parameter is used to specify a C-style or custom format
    to be used when inserting an object.  In EPFS source, the 'fmt'
    parameter is only used for custom formats, a C-style format is
    specified after the closing parenthesis.
...

special_formats

Value:
{'whole-dollars': whole_dollars, 'dollars-and-cents': dollars_and_cent\
s, 'collection-length': len_format, 'structured-text': structured_text\
, 'sql-quote': sql_quote, 'html-quote': html_quote, 'url-quote': url_q\
uote, 'url-quote-plus': url_quote_plus, 'url-unquote': url_unquote, 'u\
rl-unquote-plus': url_unquote_plus, 'multi-line': newline_to_br, 'comm\
a-numeric': thousands_commas, 'dollars-with-commas': whole_dollars_wit\
h_commas, 'dollars-and-cents-with-commas': dollars_and_cents_with_comm\
as,}

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.db.Connection-class.html0000664000076400007640000002511011122067145025062 0ustar stefanstefan qm.db.Connection
Package qm :: Module db :: Class Connection
[hide private]
[frames] | no frames]

Class Connection

source code

A wrapper around a DB 2.0 connection.

Provides a minimal but consistent interface to an underlying database connection. In particular, a 'Connection' quotes SQL queries as necessary for the underlying DB 2.0 connection.

Instance Methods [hide private]
 
__init__(self, module_name, *args, **more_args)
Uses the given DB 2.0 module to connect to a database.
source code
 
close(self) source code
 
commit(self) source code
 
rollback(self) source code
 
execute(self, sql)
Execute a SQL statement in this database.
source code
Method Details [hide private]

__init__(self, module_name, *args, **more_args)
(Constructor)

source code 

Uses the given DB 2.0 module to connect to a database.

'module_name' -- The DB 2.0-compliant module to use to connect, for example "pgdb".

'args' -- Positional arguments to pass to the module's 'connect' method.

'more_args' -- Keyword arguments to pass to the module's 'connect' method.

execute(self, sql)

source code 

Execute a SQL statement in this database.

If this database requires any overall quoting of the given SQL (for instance, doubling of %'s), it will be performed by this method.

returns -- A database cursor.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.runnable.Runnable.ResourceField-class.html0000664000076400007640000002762011122067150031466 0ustar stefanstefan qm.test.runnable.Runnable.ResourceField
qm :: test :: runnable :: Runnable :: Class Runnable :: Class ResourceField
[hide private]
[frames] | no frames]

Class ResourceField

source code

  object --+            
           |            
fields.Field --+        
               |        
fields.TextField --+    
                   |    
  fields.ChoiceField --+
                       |
                      Runnable.ResourceField

A 'ResourceField' contains the name of a resource.

The exact format of the name depends on the test database in use.

Instance Methods [hide private]
 
GetItems(self)
Return the options from which to choose.
source code

Inherited from fields.ChoiceField: FormatValueAsHtml, Validate

Inherited from fields.TextField: FormatValueAsText, GetHelp, GetValueFromDomNode, MakeDomNodeForValue, ParseFormValue, ParseTextValue, __init__

Inherited from fields.Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from fields.Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

GetItems(self)

source code 

Return the options from which to choose.

returns -- A sequence of strings, each of which will be presented as a choice for the user.

Overrides: fields.ChoiceField.GetItems
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.Session-class.html0000664000076400007640000003247511122067151024607 0ustar stefanstefan qm.web.Session
Package qm :: Module web :: Class Session
[hide private]
[frames] | no frames]

Class Session

source code

A persistent user session.

A 'Session' object represents an ongoing user interaction with the web server.

Instance Methods [hide private]
 
__init__(self, request, user_id, expiration_timeout=21600)
Create a new session.
source code
 
Touch(self)
Update the last access time on the session to now.
source code
 
GetId(self)
Return the session ID.
source code
 
GetUserId(self)
Return the ID of the user who owns this session.
source code
 
GetUser(self)
Return the user record for the owning user.
source code
 
IsDefaultUser(self)
Return true if the owning user is the default user.
source code
 
IsExpired(self)
Return true if this session has expired.
source code
 
Validate(self, request)
Make sure the session is OK for a request.
source code
Method Details [hide private]

__init__(self, request, user_id, expiration_timeout=21600)
(Constructor)

source code 

Create a new session.

'request' -- A 'WebRequest' object in response to which this session is created.

'user_id' -- The ID of the user owning the session.

'expiration_timeout -- The expiration time, in seconds. If a session is not accessed for this duration, it is expired and no longer usable.

GetUser(self)

source code 

Return the user record for the owning user.

returns -- A 'qm.user.User' object.

Validate(self, request)

source code 

Make sure the session is OK for a request.

'request' -- A 'WebRequest' object.

raises -- 'InvalidSessionError' if the session is invalid for the request.


qmtest-2.4.1/share/doc/qmtest/html/manual/random-pysrc.html0000664000076400007640000071502211122067155023307 0ustar stefanstefan random
Module random
[hide private]
[frames] | no frames]

Source Code for Module random

  1  """Random variable generators. 
  2   
  3      integers 
  4      -------- 
  5             uniform within range 
  6   
  7      sequences 
  8      --------- 
  9             pick random element 
 10             pick random sample 
 11             generate random permutation 
 12   
 13      distributions on the real line: 
 14      ------------------------------ 
 15             uniform 
 16             normal (Gaussian) 
 17             lognormal 
 18             negative exponential 
 19             gamma 
 20             beta 
 21             pareto 
 22             Weibull 
 23   
 24      distributions on the circle (angles 0 to 2pi) 
 25      --------------------------------------------- 
 26             circular uniform 
 27             von Mises 
 28   
 29  General notes on the underlying Mersenne Twister core generator: 
 30   
 31  * The period is 2**19937-1. 
 32  * It is one of the most extensively tested generators in existence. 
 33  * Without a direct way to compute N steps forward, the semantics of 
 34    jumpahead(n) are weakened to simply jump to another distant state and rely 
 35    on the large period to avoid overlapping sequences. 
 36  * The random() method is implemented in C, executes in a single Python step, 
 37    and is, therefore, threadsafe. 
 38   
 39  """ 
 40   
 41  from warnings import warn as _warn 
 42  from types import MethodType as _MethodType, BuiltinMethodType as _BuiltinMethodType 
 43  from math import log as _log, exp as _exp, pi as _pi, e as _e, ceil as _ceil 
 44  from math import sqrt as _sqrt, acos as _acos, cos as _cos, sin as _sin 
 45  from os import urandom as _urandom 
 46  from binascii import hexlify as _hexlify 
 47   
 48  __all__ = ["Random","seed","random","uniform","randint","choice","sample", 
 49             "randrange","shuffle","normalvariate","lognormvariate", 
 50             "expovariate","vonmisesvariate","gammavariate", 
 51             "gauss","betavariate","paretovariate","weibullvariate", 
 52             "getstate","setstate","jumpahead", "WichmannHill", "getrandbits", 
 53             "SystemRandom"] 
 54   
 55  NV_MAGICCONST = 4 * _exp(-0.5)/_sqrt(2.0) 
 56  TWOPI = 2.0*_pi 
 57  LOG4 = _log(4.0) 
 58  SG_MAGICCONST = 1.0 + _log(4.5) 
 59  BPF = 53        # Number of bits in a float 
 60  RECIP_BPF = 2**-BPF 
 61   
 62   
 63  # Translated by Guido van Rossum from C source provided by 
 64  # Adrian Baddeley.  Adapted by Raymond Hettinger for use with 
 65  # the Mersenne Twister  and os.urandom() core generators. 
 66   
 67  import _random 
 68   
69 -class Random(_random.Random):
70 """Random number generator base class used by bound module functions. 71 72 Used to instantiate instances of Random to get generators that don't 73 share state. Especially useful for multi-threaded programs, creating 74 a different instance of Random for each thread, and using the jumpahead() 75 method to ensure that the generated sequences seen by each thread don't 76 overlap. 77 78 Class Random can also be subclassed if you want to use a different basic 79 generator of your own devising: in that case, override the following 80 methods: random(), seed(), getstate(), setstate() and jumpahead(). 81 Optionally, implement a getrandombits() method so that randrange() 82 can cover arbitrarily large ranges. 83 84 """ 85 86 VERSION = 2 # used by getstate/setstate 87
88 - def __init__(self, x=None):
89 """Initialize an instance. 90 91 Optional argument x controls seeding, as for Random.seed(). 92 """ 93 94 self.seed(x) 95 self.gauss_next = None
96
97 - def seed(self, a=None):
98 """Initialize internal state from hashable object. 99 100 None or no argument seeds from current time or from an operating 101 system specific randomness source if available. 102 103 If a is not None or an int or long, hash(a) is used instead. 104 """ 105 106 if a is None: 107 try: 108 a = long(_hexlify(_urandom(16)), 16) 109 except NotImplementedError: 110 import time 111 a = long(time.time() * 256) # use fractional seconds 112 113 super(Random, self).seed(a) 114 self.gauss_next = None
115
116 - def getstate(self):
117 """Return internal state; can be passed to setstate() later.""" 118 return self.VERSION, super(Random, self).getstate(), self.gauss_next
119
120 - def setstate(self, state):
121 """Restore internal state from object returned by getstate().""" 122 version = state[0] 123 if version == 2: 124 version, internalstate, self.gauss_next = state 125 super(Random, self).setstate(internalstate) 126 else: 127 raise ValueError("state with version %s passed to " 128 "Random.setstate() of version %s" % 129 (version, self.VERSION))
130 131 ## ---- Methods below this point do not need to be overridden when 132 ## ---- subclassing for the purpose of using a different core generator. 133 134 ## -------------------- pickle support ------------------- 135
136 - def __getstate__(self): # for pickle
137 return self.getstate()
138
139 - def __setstate__(self, state): # for pickle
140 self.setstate(state) 141
142 - def __reduce__(self):
143 return self.__class__, (), self.getstate()
144 145 ## -------------------- integer methods ------------------- 146
147 - def randrange(self, start, stop=None, step=1, int=int, default=None, 148 maxwidth=1L<<BPF):
149 """Choose a random item from range(start, stop[, step]). 150 151 This fixes the problem with randint() which includes the 152 endpoint; in Python this is usually not what you want. 153 Do not supply the 'int', 'default', and 'maxwidth' arguments. 154 """ 155 156 # This code is a bit messy to make it fast for the 157 # common case while still doing adequate error checking. 158 istart = int(start) 159 if istart != start: 160 raise ValueError, "non-integer arg 1 for randrange()" 161 if stop is default: 162 if istart > 0: 163 if istart >= maxwidth: 164 return self._randbelow(istart) 165 return int(self.random() * istart) 166 raise ValueError, "empty range for randrange()" 167 168 # stop argument supplied. 169 istop = int(stop) 170 if istop != stop: 171 raise ValueError, "non-integer stop for randrange()" 172 width = istop - istart 173 if step == 1 and width > 0: 174 # Note that 175 # int(istart + self.random()*width) 176 # instead would be incorrect. For example, consider istart 177 # = -2 and istop = 0. Then the guts would be in 178 # -2.0 to 0.0 exclusive on both ends (ignoring that random() 179 # might return 0.0), and because int() truncates toward 0, the 180 # final result would be -1 or 0 (instead of -2 or -1). 181 # istart + int(self.random()*width) 182 # would also be incorrect, for a subtler reason: the RHS 183 # can return a long, and then randrange() would also return 184 # a long, but we're supposed to return an int (for backward 185 # compatibility). 186 187 if width >= maxwidth: 188 return int(istart + self._randbelow(width)) 189 return int(istart + int(self.random()*width)) 190 if step == 1: 191 raise ValueError, "empty range for randrange() (%d,%d, %d)" % (istart, istop, width) 192 193 # Non-unit step argument supplied. 194 istep = int(step) 195 if istep != step: 196 raise ValueError, "non-integer step for randrange()" 197 if istep > 0: 198 n = (width + istep - 1) // istep 199 elif istep < 0: 200 n = (width + istep + 1) // istep 201 else: 202 raise ValueError, "zero step for randrange()" 203 204 if n <= 0: 205 raise ValueError, "empty range for randrange()" 206 207 if n >= maxwidth: 208 return istart + istep*self._randbelow(n) 209 return istart + istep*int(self.random() * n)
210
211 - def randint(self, a, b):
212 """Return random integer in range [a, b], including both end points. 213 """ 214 215 return self.randrange(a, b+1)
216
217 - def _randbelow(self, n, _log=_log, int=int, _maxwidth=1L<<BPF, 218 _Method=_MethodType, _BuiltinMethod=_BuiltinMethodType):
219 """Return a random int in the range [0,n) 220 221 Handles the case where n has more bits than returned 222 by a single call to the underlying generator. 223 """ 224 225 try: 226 getrandbits = self.getrandbits 227 except AttributeError: 228 pass 229 else: 230 # Only call self.getrandbits if the original random() builtin method 231 # has not been overridden or if a new getrandbits() was supplied. 232 # This assures that the two methods correspond. 233 if type(self.random) is _BuiltinMethod or type(getrandbits) is _Method: 234 k = int(1.00001 + _log(n-1, 2.0)) # 2**k > n-1 > 2**(k-2) 235 r = getrandbits(k) 236 while r >= n: 237 r = getrandbits(k) 238 return r 239 if n >= _maxwidth: 240 _warn("Underlying random() generator does not supply \n" 241 "enough bits to choose from a population range this large") 242 return int(self.random() * n)
243 244 ## -------------------- sequence methods ------------------- 245
246 - def choice(self, seq):
247 """Choose a random element from a non-empty sequence.""" 248 return seq[int(self.random() * len(seq))] # raises IndexError if seq is empty
249
250 - def shuffle(self, x, random=None, int=int):
251 """x, random=random.random -> shuffle list x in place; return None. 252 253 Optional arg random is a 0-argument function returning a random 254 float in [0.0, 1.0); by default, the standard random.random. 255 """ 256 257 if random is None: 258 random = self.random 259 for i in reversed(xrange(1, len(x))): 260 # pick an element in x[:i+1] with which to exchange x[i] 261 j = int(random() * (i+1)) 262 x[i], x[j] = x[j], x[i]
263
264 - def sample(self, population, k):
265 """Chooses k unique random elements from a population sequence. 266 267 Returns a new list containing elements from the population while 268 leaving the original population unchanged. The resulting list is 269 in selection order so that all sub-slices will also be valid random 270 samples. This allows raffle winners (the sample) to be partitioned 271 into grand prize and second place winners (the subslices). 272 273 Members of the population need not be hashable or unique. If the 274 population contains repeats, then each occurrence is a possible 275 selection in the sample. 276 277 To choose a sample in a range of integers, use xrange as an argument. 278 This is especially fast and space efficient for sampling from a 279 large population: sample(xrange(10000000), 60) 280 """ 281 282 # XXX Although the documentation says `population` is "a sequence", 283 # XXX attempts are made to cater to any iterable with a __len__ 284 # XXX method. This has had mixed success. Examples from both 285 # XXX sides: sets work fine, and should become officially supported; 286 # XXX dicts are much harder, and have failed in various subtle 287 # XXX ways across attempts. Support for mapping types should probably 288 # XXX be dropped (and users should pass mapping.keys() or .values() 289 # XXX explicitly). 290 291 # Sampling without replacement entails tracking either potential 292 # selections (the pool) in a list or previous selections in a set. 293 294 # When the number of selections is small compared to the 295 # population, then tracking selections is efficient, requiring 296 # only a small set and an occasional reselection. For 297 # a larger number of selections, the pool tracking method is 298 # preferred since the list takes less space than the 299 # set and it doesn't suffer from frequent reselections. 300 301 n = len(population) 302 if not 0 <= k <= n: 303 raise ValueError, "sample larger than population" 304 random = self.random 305 _int = int 306 result = [None] * k 307 setsize = 21 # size of a small set minus size of an empty list 308 if k > 5: 309 setsize += 4 ** _ceil(_log(k * 3, 4)) # table size for big sets 310 if n <= setsize or hasattr(population, "keys"): 311 # An n-length list is smaller than a k-length set, or this is a 312 # mapping type so the other algorithm wouldn't work. 313 pool = list(population) 314 for i in xrange(k): # invariant: non-selected at [0,n-i) 315 j = _int(random() * (n-i)) 316 result[i] = pool[j] 317 pool[j] = pool[n-i-1] # move non-selected item into vacancy 318 else: 319 try: 320 selected = set() 321 selected_add = selected.add 322 for i in xrange(k): 323 j = _int(random() * n) 324 while j in selected: 325 j = _int(random() * n) 326 selected_add(j) 327 result[i] = population[j] 328 except (TypeError, KeyError): # handle (at least) sets 329 if isinstance(population, list): 330 raise 331 return self.sample(tuple(population), k) 332 return result
333 334 ## -------------------- real-valued distributions ------------------- 335 336 ## -------------------- uniform distribution ------------------- 337
338 - def uniform(self, a, b):
339 """Get a random number in the range [a, b).""" 340 return a + (b-a) * self.random()
341 342 ## -------------------- normal distribution -------------------- 343
344 - def normalvariate(self, mu, sigma):
345 """Normal distribution. 346 347 mu is the mean, and sigma is the standard deviation. 348 349 """ 350 # mu = mean, sigma = standard deviation 351 352 # Uses Kinderman and Monahan method. Reference: Kinderman, 353 # A.J. and Monahan, J.F., "Computer generation of random 354 # variables using the ratio of uniform deviates", ACM Trans 355 # Math Software, 3, (1977), pp257-260. 356 357 random = self.random 358 while 1: 359 u1 = random() 360 u2 = 1.0 - random() 361 z = NV_MAGICCONST*(u1-0.5)/u2 362 zz = z*z/4.0 363 if zz <= -_log(u2): 364 break 365 return mu + z*sigma
366 367 ## -------------------- lognormal distribution -------------------- 368
369 - def lognormvariate(self, mu, sigma):
370 """Log normal distribution. 371 372 If you take the natural logarithm of this distribution, you'll get a 373 normal distribution with mean mu and standard deviation sigma. 374 mu can have any value, and sigma must be greater than zero. 375 376 """ 377 return _exp(self.normalvariate(mu, sigma))
378 379 ## -------------------- exponential distribution -------------------- 380
381 - def expovariate(self, lambd):
382 """Exponential distribution. 383 384 lambd is 1.0 divided by the desired mean. (The parameter would be 385 called "lambda", but that is a reserved word in Python.) Returned 386 values range from 0 to positive infinity. 387 388 """ 389 # lambd: rate lambd = 1/mean 390 # ('lambda' is a Python reserved word) 391 392 random = self.random 393 u = random() 394 while u <= 1e-7: 395 u = random() 396 return -_log(u)/lambd
397 398 ## -------------------- von Mises distribution -------------------- 399
400 - def vonmisesvariate(self, mu, kappa):
401 """Circular data distribution. 402 403 mu is the mean angle, expressed in radians between 0 and 2*pi, and 404 kappa is the concentration parameter, which must be greater than or 405 equal to zero. If kappa is equal to zero, this distribution reduces 406 to a uniform random angle over the range 0 to 2*pi. 407 408 """ 409 # mu: mean angle (in radians between 0 and 2*pi) 410 # kappa: concentration parameter kappa (>= 0) 411 # if kappa = 0 generate uniform random angle 412 413 # Based upon an algorithm published in: Fisher, N.I., 414 # "Statistical Analysis of Circular Data", Cambridge 415 # University Press, 1993. 416 417 # Thanks to Magnus Kessler for a correction to the 418 # implementation of step 4. 419 420 random = self.random 421 if kappa <= 1e-6: 422 return TWOPI * random() 423 424 a = 1.0 + _sqrt(1.0 + 4.0 * kappa * kappa) 425 b = (a - _sqrt(2.0 * a))/(2.0 * kappa) 426 r = (1.0 + b * b)/(2.0 * b) 427 428 while 1: 429 u1 = random() 430 431 z = _cos(_pi * u1) 432 f = (1.0 + r * z)/(r + z) 433 c = kappa * (r - f) 434 435 u2 = random() 436 437 if u2 < c * (2.0 - c) or u2 <= c * _exp(1.0 - c): 438 break 439 440 u3 = random() 441 if u3 > 0.5: 442 theta = (mu % TWOPI) + _acos(f) 443 else: 444 theta = (mu % TWOPI) - _acos(f) 445 446 return theta
447 448 ## -------------------- gamma distribution -------------------- 449
450 - def gammavariate(self, alpha, beta):
451 """Gamma distribution. Not the gamma function! 452 453 Conditions on the parameters are alpha > 0 and beta > 0. 454 455 """ 456 457 # alpha > 0, beta > 0, mean is alpha*beta, variance is alpha*beta**2 458 459 # Warning: a few older sources define the gamma distribution in terms 460 # of alpha > -1.0 461 if alpha <= 0.0 or beta <= 0.0: 462 raise ValueError, 'gammavariate: alpha and beta must be > 0.0' 463 464 random = self.random 465 if alpha > 1.0: 466 467 # Uses R.C.H. Cheng, "The generation of Gamma 468 # variables with non-integral shape parameters", 469 # Applied Statistics, (1977), 26, No. 1, p71-74 470 471 ainv = _sqrt(2.0 * alpha - 1.0) 472 bbb = alpha - LOG4 473 ccc = alpha + ainv 474 475 while 1: 476 u1 = random() 477 if not 1e-7 < u1 < .9999999: 478 continue 479 u2 = 1.0 - random() 480 v = _log(u1/(1.0-u1))/ainv 481 x = alpha*_exp(v) 482 z = u1*u1*u2 483 r = bbb+ccc*v-x 484 if r + SG_MAGICCONST - 4.5*z >= 0.0 or r >= _log(z): 485 return x * beta 486 487 elif alpha == 1.0: 488 # expovariate(1) 489 u = random() 490 while u <= 1e-7: 491 u = random() 492 return -_log(u) * beta 493 494 else: # alpha is between 0 and 1 (exclusive) 495 496 # Uses ALGORITHM GS of Statistical Computing - Kennedy & Gentle 497 498 while 1: 499 u = random() 500 b = (_e + alpha)/_e 501 p = b*u 502 if p <= 1.0: 503 x = p ** (1.0/alpha) 504 else: 505 x = -_log((b-p)/alpha) 506 u1 = random() 507 if p > 1.0: 508 if u1 <= x ** (alpha - 1.0): 509 break 510 elif u1 <= _exp(-x): 511 break 512 return x * beta
513 514 ## -------------------- Gauss (faster alternative) -------------------- 515
516 - def gauss(self, mu, sigma):
517 """Gaussian distribution. 518 519 mu is the mean, and sigma is the standard deviation. This is 520 slightly faster than the normalvariate() function. 521 522 Not thread-safe without a lock around calls. 523 524 """ 525 526 # When x and y are two variables from [0, 1), uniformly 527 # distributed, then 528 # 529 # cos(2*pi*x)*sqrt(-2*log(1-y)) 530 # sin(2*pi*x)*sqrt(-2*log(1-y)) 531 # 532 # are two *independent* variables with normal distribution 533 # (mu = 0, sigma = 1). 534 # (Lambert Meertens) 535 # (corrected version; bug discovered by Mike Miller, fixed by LM) 536 537 # Multithreading note: When two threads call this function 538 # simultaneously, it is possible that they will receive the 539 # same return value. The window is very small though. To 540 # avoid this, you have to use a lock around all calls. (I 541 # didn't want to slow this down in the serial case by using a 542 # lock here.) 543 544 random = self.random 545 z = self.gauss_next 546 self.gauss_next = None 547 if z is None: 548 x2pi = random() * TWOPI 549 g2rad = _sqrt(-2.0 * _log(1.0 - random())) 550 z = _cos(x2pi) * g2rad 551 self.gauss_next = _sin(x2pi) * g2rad 552 553 return mu + z*sigma
554 555 ## -------------------- beta -------------------- 556 ## See 557 ## http://sourceforge.net/bugs/?func=detailbug&bug_id=130030&group_id=5470 558 ## for Ivan Frohne's insightful analysis of why the original implementation: 559 ## 560 ## def betavariate(self, alpha, beta): 561 ## # Discrete Event Simulation in C, pp 87-88. 562 ## 563 ## y = self.expovariate(alpha) 564 ## z = self.expovariate(1.0/beta) 565 ## return z/(y+z) 566 ## 567 ## was dead wrong, and how it probably got that way. 568
569 - def betavariate(self, alpha, beta):
570 """Beta distribution. 571 572 Conditions on the parameters are alpha > 0 and beta > 0. 573 Returned values range between 0 and 1. 574 575 """ 576 577 # This version due to Janne Sinkkonen, and matches all the std 578 # texts (e.g., Knuth Vol 2 Ed 3 pg 134 "the beta distribution"). 579 y = self.gammavariate(alpha, 1.) 580 if y == 0: 581 return 0.0 582 else: 583 return y / (y + self.gammavariate(beta, 1.))
584 585 ## -------------------- Pareto -------------------- 586
587 - def paretovariate(self, alpha):
588 """Pareto distribution. alpha is the shape parameter.""" 589 # Jain, pg. 495 590 591 u = 1.0 - self.random() 592 return 1.0 / pow(u, 1.0/alpha)
593 594 ## -------------------- Weibull -------------------- 595
596 - def weibullvariate(self, alpha, beta):
597 """Weibull distribution. 598 599 alpha is the scale parameter and beta is the shape parameter. 600 601 """ 602 # Jain, pg. 499; bug fix courtesy Bill Arms 603 604 u = 1.0 - self.random() 605 return alpha * pow(-_log(u), 1.0/beta)
606 607 ## -------------------- Wichmann-Hill ------------------- 608
609 -class WichmannHill(Random):
610 611 VERSION = 1 # used by getstate/setstate 612
613 - def seed(self, a=None):
614 """Initialize internal state from hashable object. 615 616 None or no argument seeds from current time or from an operating 617 system specific randomness source if available. 618 619 If a is not None or an int or long, hash(a) is used instead. 620 621 If a is an int or long, a is used directly. Distinct values between 622 0 and 27814431486575L inclusive are guaranteed to yield distinct 623 internal states (this guarantee is specific to the default 624 Wichmann-Hill generator). 625 """ 626 627 if a is None: 628 try: 629 a = long(_hexlify(_urandom(16)), 16) 630 except NotImplementedError: 631 import time 632 a = long(time.time() * 256) # use fractional seconds 633 634 if not isinstance(a, (int, long)): 635 a = hash(a) 636 637 a, x = divmod(a, 30268) 638 a, y = divmod(a, 30306) 639 a, z = divmod(a, 30322) 640 self._seed = int(x)+1, int(y)+1, int(z)+1 641 642 self.gauss_next = None
643
644 - def random(self):
645 """Get the next random number in the range [0.0, 1.0).""" 646 647 # Wichman-Hill random number generator. 648 # 649 # Wichmann, B. A. & Hill, I. D. (1982) 650 # Algorithm AS 183: 651 # An efficient and portable pseudo-random number generator 652 # Applied Statistics 31 (1982) 188-190 653 # 654 # see also: 655 # Correction to Algorithm AS 183 656 # Applied Statistics 33 (1984) 123 657 # 658 # McLeod, A. I. (1985) 659 # A remark on Algorithm AS 183 660 # Applied Statistics 34 (1985),198-200 661 662 # This part is thread-unsafe: 663 # BEGIN CRITICAL SECTION 664 x, y, z = self._seed 665 x = (171 * x) % 30269 666 y = (172 * y) % 30307 667 z = (170 * z) % 30323 668 self._seed = x, y, z 669 # END CRITICAL SECTION 670 671 # Note: on a platform using IEEE-754 double arithmetic, this can 672 # never return 0.0 (asserted by Tim; proof too long for a comment). 673 return (x/30269.0 + y/30307.0 + z/30323.0) % 1.0
674
675 - def getstate(self):
676 """Return internal state; can be passed to setstate() later.""" 677 return self.VERSION, self._seed, self.gauss_next
678
679 - def setstate(self, state):
680 """Restore internal state from object returned by getstate().""" 681 version = state[0] 682 if version == 1: 683 version, self._seed, self.gauss_next = state 684 else: 685 raise ValueError("state with version %s passed to " 686 "Random.setstate() of version %s" % 687 (version, self.VERSION))
688
689 - def jumpahead(self, n):
690 """Act as if n calls to random() were made, but quickly. 691 692 n is an int, greater than or equal to 0. 693 694 Example use: If you have 2 threads and know that each will 695 consume no more than a million random numbers, create two Random 696 objects r1 and r2, then do 697 r2.setstate(r1.getstate()) 698 r2.jumpahead(1000000) 699 Then r1 and r2 will use guaranteed-disjoint segments of the full 700 period. 701 """ 702 703 if not n >= 0: 704 raise ValueError("n must be >= 0") 705 x, y, z = self._seed 706 x = int(x * pow(171, n, 30269)) % 30269 707 y = int(y * pow(172, n, 30307)) % 30307 708 z = int(z * pow(170, n, 30323)) % 30323 709 self._seed = x, y, z
710
711 - def __whseed(self, x=0, y=0, z=0):
712 """Set the Wichmann-Hill seed from (x, y, z). 713 714 These must be integers in the range [0, 256). 715 """ 716 717 if not type(x) == type(y) == type(z) == int: 718 raise TypeError('seeds must be integers') 719 if not (0 <= x < 256 and 0 <= y < 256 and 0 <= z < 256): 720 raise ValueError('seeds must be in range(0, 256)') 721 if 0 == x == y == z: 722 # Initialize from current time 723 import time 724 t = long(time.time() * 256) 725 t = int((t&0xffffff) ^ (t>>24)) 726 t, x = divmod(t, 256) 727 t, y = divmod(t, 256) 728 t, z = divmod(t, 256) 729 # Zero is a poor seed, so substitute 1 730 self._seed = (x or 1, y or 1, z or 1) 731 732 self.gauss_next = None
733
734 - def whseed(self, a=None):
735 """Seed from hashable object's hash code. 736 737 None or no argument seeds from current time. It is not guaranteed 738 that objects with distinct hash codes lead to distinct internal 739 states. 740 741 This is obsolete, provided for compatibility with the seed routine 742 used prior to Python 2.1. Use the .seed() method instead. 743 """ 744 745 if a is None: 746 self.__whseed() 747 return 748 a = hash(a) 749 a, x = divmod(a, 256) 750 a, y = divmod(a, 256) 751 a, z = divmod(a, 256) 752 x = (x + a) % 256 or 1 753 y = (y + a) % 256 or 1 754 z = (z + a) % 256 or 1 755 self.__whseed(x, y, z)
756 757 ## --------------- Operating System Random Source ------------------ 758
759 -class SystemRandom(Random):
760 """Alternate random number generator using sources provided 761 by the operating system (such as /dev/urandom on Unix or 762 CryptGenRandom on Windows). 763 764 Not available on all systems (see os.urandom() for details). 765 """ 766
767 - def random(self):
768 """Get the next random number in the range [0.0, 1.0).""" 769 return (long(_hexlify(_urandom(7)), 16) >> 3) * RECIP_BPF
770
771 - def getrandbits(self, k):
772 """getrandbits(k) -> x. Generates a long int with k random bits.""" 773 if k <= 0: 774 raise ValueError('number of bits must be greater than zero') 775 if k != int(k): 776 raise TypeError('number of bits should be an integer') 777 bytes = (k + 7) // 8 # bits / 8 and rounded up 778 x = long(_hexlify(_urandom(bytes)), 16) 779 return x >> (bytes * 8 - k) # trim excess bits
780
781 - def _stub(self, *args, **kwds):
782 "Stub method. Not used for a system random number generator." 783 return None
784 seed = jumpahead = _stub 785
786 - def _notimplemented(self, *args, **kwds):
787 "Method should not be called for a system random number generator." 788 raise NotImplementedError('System entropy source does not have state.')
789 getstate = setstate = _notimplemented
790 791 ## -------------------- test program -------------------- 792
793 -def _test_generator(n, func, args):
794 import time 795 print n, 'times', func.__name__ 796 total = 0.0 797 sqsum = 0.0 798 smallest = 1e10 799 largest = -1e10 800 t0 = time.time() 801 for i in range(n): 802 x = func(*args) 803 total += x 804 sqsum = sqsum + x*x 805 smallest = min(x, smallest) 806 largest = max(x, largest) 807 t1 = time.time() 808 print round(t1-t0, 3), 'sec,', 809 avg = total/n 810 stddev = _sqrt(sqsum/n - avg*avg) 811 print 'avg %g, stddev %g, min %g, max %g' % \ 812 (avg, stddev, smallest, largest)
813 814
815 -def _test(N=2000):
816 _test_generator(N, random, ()) 817 _test_generator(N, normalvariate, (0.0, 1.0)) 818 _test_generator(N, lognormvariate, (0.0, 1.0)) 819 _test_generator(N, vonmisesvariate, (0.0, 1.0)) 820 _test_generator(N, gammavariate, (0.01, 1.0)) 821 _test_generator(N, gammavariate, (0.1, 1.0)) 822 _test_generator(N, gammavariate, (0.1, 2.0)) 823 _test_generator(N, gammavariate, (0.5, 1.0)) 824 _test_generator(N, gammavariate, (0.9, 1.0)) 825 _test_generator(N, gammavariate, (1.0, 1.0)) 826 _test_generator(N, gammavariate, (2.0, 1.0)) 827 _test_generator(N, gammavariate, (20.0, 1.0)) 828 _test_generator(N, gammavariate, (200.0, 1.0)) 829 _test_generator(N, gauss, (0.0, 1.0)) 830 _test_generator(N, betavariate, (3.0, 3.0))
831 832 # Create one instance, seeded from current time, and export its methods 833 # as module-level functions. The functions share state across all uses 834 #(both in the user's code and in the Python libraries), but that's fine 835 # for most programs and is easier for the casual user than making them 836 # instantiate their own Random() instance. 837 838 _inst = Random() 839 seed = _inst.seed 840 random = _inst.random 841 uniform = _inst.uniform 842 randint = _inst.randint 843 choice = _inst.choice 844 randrange = _inst.randrange 845 sample = _inst.sample 846 shuffle = _inst.shuffle 847 normalvariate = _inst.normalvariate 848 lognormvariate = _inst.lognormvariate 849 expovariate = _inst.expovariate 850 vonmisesvariate = _inst.vonmisesvariate 851 gammavariate = _inst.gammavariate 852 gauss = _inst.gauss 853 betavariate = _inst.betavariate 854 paretovariate = _inst.paretovariate 855 weibullvariate = _inst.weibullvariate 856 getstate = _inst.getstate 857 setstate = _inst.setstate 858 jumpahead = _inst.jumpahead 859 getrandbits = _inst.getrandbits 860 861 if __name__ == '__main__': 862 _test() 863

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.attachment.TemporaryAttachmentStore-class.html0000664000076400007640000002667211122067145031554 0ustar stefanstefan qm.attachment.TemporaryAttachmentStore
Package qm :: Module attachment :: Class TemporaryAttachmentStore
[hide private]
[frames] | no frames]

Class TemporaryAttachmentStore

source code

     object --+        
              |        
AttachmentStore --+    
                  |    
FileAttachmentStore --+
                      |
                     TemporaryAttachmentStore

Temporary storage for attachment data.

A 'TemporaryAttachmentStore' stores attachment data in a temporary location, for up to the lifetime of the running program. When the program ends, all temporarily stored attachment data is deleted.

A data object in the temporary store is identified by its location. Locations should be generated by 'make_temporary_location'.

Instance Methods [hide private]
 
__init__(self)
Construct a temporary attachment store.
source code
 
HandleUploadRequest(self, request)
Handle a web request to upload attachment data.
source code

Inherited from FileAttachmentStore: GetData, GetDataFile, GetSize, Remove, Store

Inherited from AttachmentStore: HandleDownloadRequest

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self)
(Constructor)

source code 

Construct a temporary attachment store.

The store is initially empty.

Overrides: object.__init__

HandleUploadRequest(self, request)

source code 

Handle a web request to upload attachment data.

Store the attachment data contained in the request as a temporary attachment. It is assumed that the request is being submitted from a popup upload browser window, so the returned HTML page instructs the window to close itself.

'request' -- A 'WebRequest' object.

returns -- HTML text of a page that instructs the browser window to close.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.structured_text.HtmlFormatter-class.html0000664000076400007640000011031111122067146030435 0ustar stefanstefan qm.structured_text.HtmlFormatter
Package qm :: Module structured_text :: Class HtmlFormatter
[hide private]
[frames] | no frames]

Class HtmlFormatter

source code

Formatter --+
            |
           HtmlFormatter

Formatter for generating HTML from structured text.

Instance Methods [hide private]
 
__init__(self, output_file=sys.stdout)
Create a new HTML formatter.
source code
 
End(self)
End the processed text document.
source code
 
WriteText(self, text)
Write ordinary text.
source code
 
StartList(self, type)
Start a list environment of type 'type'.
source code
 
EndList(self, type)
End a list environment of type 'type'.
source code
 
StartItem(self, type, label=None)
Begin an element to the environment of type 'type'.
source code
 
FinishDefinedTerm(self)
Finish the definition of a term in a definition list.
source code
 
EndItem(self, type)
End an element in the environment of type 'type'.
source code
 
StartStyle(self, style)
Start a new text style 'style'.
source code
 
EndStyle(self, style)
End the text style 'style'.
source code
 
StartLink(self, target)
Being a hyperlink to 'target'.
source code
 
EndLink(self)
End a hyperlink.
source code
 
__Write(self, text) source code
Class Variables [hide private]
  __start_list_tags = {'definition list': '<dl>\n', 'ordered lis...
  __end_list_tags = {'definition list': '</dl>\n', 'ordered list...
  __start_item_tags = {'definition list': '<dt>', 'ordered list'...
  __end_item_tags = {'definition list': '</dd>\n', 'ordered list...
  __start_style_tags = {'emphasized': '<em>', 'literal': '<tt>',...
  __end_style_tags = {'emphasized': '</em>', 'literal': '</tt>',...
Method Details [hide private]

__init__(self, output_file=sys.stdout)
(Constructor)

source code 

Create a new HTML formatter.

'output_file' -- A file object to which HTML source is written.

StartItem(self, type, label=None)

source code 

Begin an element to the environment of type 'type'.

'label' -- If type is "ordered list", this is the label for this list element.


Class Variable Details [hide private]

__start_list_tags

Value:
{'definition list': '''<dl>
''',
 'ordered list': '''<ol>
''',
 'paragraph': '',
 'unordered list': '''<ul>
''',
 'verbatim': ''}

__end_list_tags

Value:
{'definition list': '''</dl>
''',
 'ordered list': '''</ol>
''',
 'paragraph': '',
 'unordered list': '''</ul>
''',
 'verbatim': ''}

__start_item_tags

Value:
{'definition list': '<dt>',
 'ordered list': '''<li>
''',
 'paragraph': '<p>',
 'unordered list': '''<li>
''',
 'verbatim': ''}

__end_item_tags

Value:
{'definition list': '''</dd>
''',
 'ordered list': '''</li>
''',
 'paragraph': '''</p>
''',
 'unordered list': '''</li>
''',
...

__start_style_tags

Value:
{'emphasized': '<em>',
 'literal': '<tt>',
 'strong': '<strong>',
 'underlined': '<u>',
 'verbatim': '<pre>\'<span class="verbatim">'}

__end_style_tags

Value:
{'emphasized': '</em>',
 'literal': '</tt>',
 'strong': '</strong>',
 'underlined': '</u>',
 'verbatim': '</span>\'</pre>'}

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.host-module.html0000664000076400007640000000205511122067144024321 0ustar stefanstefan host

Module host


Classes

Host

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.classes.dejagnu_stream.DejaGNUStream-class.html0000664000076400007640000006440711122067147032407 0ustar stefanstefan qm.test.classes.dejagnu_stream.DejaGNUStream
Package qm :: Package test :: Package classes :: Module dejagnu_stream :: Class DejaGNUStream
[hide private]
[frames] | no frames]

Class DejaGNUStream

source code

                 object --+            
                          |            
        extension.Extension --+        
                              |        
     result_stream.ResultStream --+    
                                  |    
file_result_stream.FileResultStream --+
                                      |
                                     DejaGNUStream

A 'DejaGNUStream' formats its output like DejaGNU.

Nested Classes [hide private]

Inherited from extension.Extension: Type, __metaclass__

Instance Methods [hide private]
 
__init__(self, arguments=None, **args)
Construct a new 'Extension'.
source code
 
WriteResult(self, result)
Output a test result.
source code
 
Summarize(self)
Output summary information about the results.
source code

Inherited from result_stream.ResultStream: WriteAllAnnotations, WriteAnnotation

Inherited from extension.Extension: GetClassName, GetExplicitArguments, MakeDomDocument, MakeDomElement, Write, __getattr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Class Variables [hide private]
  arguments = [qm.fields.BooleanField(name= "show_expected_outco...
A list of the arguments to the extension class.
  __summary_outcomes = [DejaGNUTest.PASS, DejaGNUTest.FAIL, Deja...
The outcomes for which summary output should be produced.
  __outcome_descs = {DejaGNUTest.PASS: "expected passes", DejaGN...
A map from DejaGNU outcomes to descriptions.
  __expected_outcomes = DejaGNUTest.PASS, DejaGNUTest.KFAIL, Dej...
The DejaGNU outcomes that are considered "expected" results.

Inherited from file_result_stream.FileResultStream: file, filename

Inherited from result_stream.ResultStream: expected_outcomes, kind

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, arguments=None, **args)
(Constructor)

source code 

Construct a new 'Extension'.

'args': Keyword arguments providing values for Extension parameters. The values should be appropriate for the corresponding fields. Derived classes must pass along any unrecognized keyword arguments to this method so that additional arguments can be added in the future without necessitating changes to derived classes.

This method will place all of the arguments into this objects instance dictionary.

Derived classes may override this method, but should call this method during their processing.

Overrides: object.__init__
(inherited documentation)

WriteResult(self, result)

source code 

Output a test result.

Subclasses must override this method; the default implementation raises a 'NotImplementedError'.

'result' -- A 'Result'.

Overrides: result_stream.ResultStream.WriteResult
(inherited documentation)

Summarize(self)

source code 

Output summary information about the results.

When this method is called, the test run is complete. Summary information should be displayed for the user, if appropriate. Any finalization, such as the closing of open files, should also be performed at this point.

Derived class methods may override this method. They should, however, invoke this version before returning.

Overrides: result_stream.ResultStream.Summarize
(inherited documentation)

Class Variable Details [hide private]

arguments

A list of the arguments to the extension class.

Each element of this list should be an instance of 'Field'. The 'Field' instance describes the argument.

Derived classes may redefine this class variable. However, derived classes should not explicitly include the arguments from base classes; QMTest will automatically combine all the arguments found throughout the class hierarchy.

Value:
[qm.fields.BooleanField(name= "show_expected_outcomes", title= "Show E\
xpected Outcomes", description= """True if expected outcomes should be\
 displayed.

            By default, only information about unexpected outcomes is
            displayed.""", default_value= "false")]

__summary_outcomes

The outcomes for which summary output should be produced.

Value:
[DejaGNUTest.PASS, DejaGNUTest.FAIL, DejaGNUTest.KFAIL, DejaGNUTest.KP\
ASS, DejaGNUTest.XPASS, DejaGNUTest.XFAIL, DejaGNUTest.UNRESOLVED, Dej\
aGNUTest.UNTESTED, DejaGNUTest.UNSUPPORTED]

__outcome_descs

A map from DejaGNU outcomes to descriptions.

See 'init_testcounts' in the DejaGNU distribution for the code emulated by this table.

Value:
{DejaGNUTest.PASS: "expected passes", DejaGNUTest.FAIL: "unexpected fa\
ilures", DejaGNUTest.KPASS: "unexpected successes", DejaGNUTest.KFAIL:\
 "expected failures", DejaGNUTest.XPASS: "unexpected successes", DejaG\
NUTest.XFAIL: "expected failures", DejaGNUTest.UNRESOLVED: "unresolved\
 testcases", DejaGNUTest.UNTESTED: "untested testcases", DejaGNUTest.U\
NSUPPORTED: "unsupported tests",}

__expected_outcomes

The DejaGNU outcomes that are considered "expected" results.

DejaGNU results with these outcomes are not displayed unless 'show_expected_outcomes' is true.

Value:
DejaGNUTest.PASS, DejaGNUTest.KFAIL, DejaGNUTest.XFAIL, DejaGNUTest.UN\
RESOLVED, DejaGNUTest.UNSUPPORTED, DejaGNUTest.UNTESTED

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.web.web.LoadExpectationsPage-class.html0000664000076400007640000003563211122067151030757 0ustar stefanstefan qm.test.web.web.LoadExpectationsPage
Package qm :: Package test :: Package web :: Module web :: Class LoadExpectationsPage
[hide private]
[frames] | no frames]

Class LoadExpectationsPage

source code

web.DtmlPage --+        
               |        
 DefaultDtmlPage --+    
                   |    
          QMTestPage --+
                       |
                      LoadExpectationsPage

DTML page for uploading a context.

Nested Classes [hide private]

Inherited from web.DtmlPage: default_class

Instance Methods [hide private]
 
__init__(self, server)
Construct a new 'LoadExpectationsPage'.
source code

Inherited from QMTestPage: GenerateHtmlHeader, GenerateStartBody, GetExpectationUrl, GetRefreshDelay, IsFinished

Inherited from DefaultDtmlPage: FormatId, GetDatabase, GetMainPageUrl, GetName, GetOutcomePercentages, GetResultsByOutcome, HasModifiableExpectations, IsLabelInDirectory, MakeListingUrl

Inherited from web.DtmlPage: GenerateEndBody, GenerateEndScript, GenerateStartScript, GenerateXMLHeader, GetProgramName, MakeButton, MakeImageUrl, MakeLoginForm, MakeRule, MakeSpacer, UserIsInGroup, WebRequest, __call__

Class Variables [hide private]
  title = "Load Expectations"
The title for the page.
  heading = "Load expectations from a file."
The heading printed across the top of the page.
  prompt = "The file from which to load expectations." ""
The prompt for the file name.
  submit_url = "submit-expectations"
The URL to which the file should be submitted.

Inherited from DefaultDtmlPage: EXPECTATION_KINDS, EXPECTED, NEGATIVE_UNEXPECTED, POSITIVE_UNEXPECTED, html_generator, outcomes

Inherited from web.DtmlPage: common_javascript, html_stylesheet, qm_bug_system_url, web

Method Details [hide private]

__init__(self, server)
(Constructor)

source code 

Construct a new 'LoadExpectationsPage'.

'server' -- The 'QMTestServer' creating this page.

Overrides: web.DtmlPage.__init__

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.fields.TextField-class.html0000664000076400007640000007370011122067146025545 0ustar stefanstefan qm.fields.TextField
qm :: fields :: TextField :: Class TextField
[hide private]
[frames] | no frames]

Class TextField

source code

object --+    
         |    
     Field --+
             |
            TextField
Known Subclasses:

A field that contains text.

Instance Methods [hide private]
 
__init__(self, name='', default_value='', multiline='false', structured='false', verbatim='false', not_empty_text='false', **properties)
Construct a new 'TextField'.
source code
 
GetHelp(self)
Generate help text about this field in structured text format.
source code
 
FormatValueAsText(self, value, columns=72)
Return a plain text rendering of a 'value' for this field.
source code
 
FormatValueAsHtml(self, server, value, style, name=None)
Return an HTML rendering of a 'value' for this field.
source code
 
MakeDomNodeForValue(self, value, document)
Generate a DOM element node for a value of this field.
source code
 
Validate(self, value)
Validate a field value.
source code
 
ParseFormValue(self, request, name, attachment_stores)
Convert a value submitted from an HTML form.
source code
 
ParseTextValue(self, value)
Parse a value represented as a string.
source code
 
GetValueFromDomNode(self, node, attachment_store)
Return a value for this field represented by DOM 'node'.
source code

Inherited from Field: GetBriefDescription, GetDefaultValue, GetDescription, GetHtmlFormFieldName, GetHtmlHelp, GetName, GetSubfields, GetTitle, IsComputed, IsHidden, IsReadOnly, SetName, __repr__

Inherited from object: __delattr__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __setattr__, __str__

Class Variables [hide private]

Inherited from Field: form_field_prefix

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

__init__(self, name='', default_value='', multiline='false', structured='false', verbatim='false', not_empty_text='false', **properties)
(Constructor)

source code 

Construct a new 'TextField'.

'multiline' -- If false, a value for this field is a single line of text. If true, multi-line text is allowed.

'structured' -- If true, the field contains structured text.

'verbatim' -- If true, the contents of the field are treated as preformatted text.

'not_empty_text' -- The value of this field is considered invalid if it empty or composed only of whitespace.

'properties' -- A dictionary of other keyword arguments which are provided to the base class constructor.

Overrides: object.__init__

GetHelp(self)

source code 

Generate help text about this field in structured text format.

Overrides: Field.GetHelp
(inherited documentation)

FormatValueAsText(self, value, columns=72)

source code 

Return a plain text rendering of a 'value' for this field.

'columns' -- The maximum width of each line of text.

returns -- A plain-text string representing 'value'.

Overrides: Field.FormatValueAsText
(inherited documentation)

FormatValueAsHtml(self, server, value, style, name=None)

source code 

Return an HTML rendering of a 'value' for this field.

'server' -- The 'WebServer' in which the HTML will be displayed.

'value' -- The value for this field. May be 'None', which renders a default value (useful for blank forms).

'style' -- The rendering style. Can be "full" or "brief" (both read-only), or "new" or "edit" or "hidden".

'name' -- The name to use for the primary HTML form element containing the value of this field, if 'style' specifies the generation of form elements. If 'name' is 'None', the value returned by 'GetHtmlFormFieldName()' should be used.

returns -- A string containing the HTML representation of 'value'.

Overrides: Field.FormatValueAsHtml
(inherited documentation)

MakeDomNodeForValue(self, value, document)

source code 

Generate a DOM element node for a value of this field.

'value' -- The value to represent.

'document' -- The containing DOM document node.

Overrides: Field.MakeDomNodeForValue
(inherited documentation)

Validate(self, value)

source code 

Validate a field value.

For an acceptable type and value, return the representation of 'value' in the underlying field storage.

'value' -- A value to validate for this field.

returns -- If the 'value' is valid, returns 'value' or an equivalent "canonical" version of 'value'. (For example, this function may search a hash table and return an equivalent entry from the hash table.)

This function must raise an exception if the value is not valid. The string representation of the exception will be used as an error message in some situations.

Implementations of this method must be idempotent.

Overrides: Field.Validate
(inherited documentation)

ParseFormValue(self, request, name, attachment_stores)

source code 

Convert a value submitted from an HTML form.

'request' -- The 'WebRequest' containing a value corresponding to this field.

'name' -- The name corresponding to this field in the 'request'.

'attachment_stores' -- A dictionary mapping 'AttachmentStore' ids (in the sense of Python's 'id' built-in) to the 'AttachmentStore's themselves.

returns -- A pair '(value, redisplay)'. 'value' is the value for this field, as indicated in 'request'. 'redisplay' is true if and only if the form should be redisplayed, rather than committed. If an error occurs, an exception is thrown.

Overrides: Field.ParseFormValue
(inherited documentation)

ParseTextValue(self, value)

source code 

Parse a value represented as a string.

'value' -- A string representing the value.

returns -- The corresponding field value. The value returned should be processed by 'Validate' to ensure that it is valid before it is returned.

Overrides: Field.ParseTextValue
(inherited documentation)

GetValueFromDomNode(self, node, attachment_store)

source code 

Return a value for this field represented by DOM 'node'.

This method does not validate the value for this particular instance; it only makes sure the node is well-formed, and returns a value of the correct Python type.

'node' -- The DOM node that is being evaluated.

'attachment_store' -- For attachments, the store that should be used.

If the 'node' is incorrectly formed, this method should raise an exception.

Overrides: Field.GetValueFromDomNode
(inherited documentation)

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.web.HTTPServer-class.html0000664000076400007640000002177711122067151025135 0ustar stefanstefan qm.web.HTTPServer
Package qm :: Module web :: Class HTTPServer
[hide private]
[frames] | no frames]

Class HTTPServer

source code

SocketServer.BaseServer --+        
                          |        
     SocketServer.TCPServer --+    
                              |    
      BaseHTTPServer.HTTPServer --+
                                  |
                                 HTTPServer
Known Subclasses:

Workaround for problems in 'BaseHTTPServer.HTTPServer'.

The Python 1.5.2 library's implementation of 'BaseHTTPServer.HTTPServer.server_bind' seems to have difficulties when the local host address cannot be resolved by 'gethostbyaddr'. This may happen for a variety of reasons, such as reverse DNS misconfiguration. This subclass fixes that problem.

Instance Methods [hide private]
 
server_bind(self)
Override 'server_bind' to store the server name.
source code

Inherited from SocketServer.TCPServer: __init__, close_request, fileno, get_request, server_activate, server_close

Inherited from SocketServer.BaseServer: finish_request, handle_error, handle_request, process_request, serve_forever, verify_request

Class Variables [hide private]

Inherited from BaseHTTPServer.HTTPServer: allow_reuse_address

Inherited from SocketServer.TCPServer: address_family, request_queue_size, socket_type

Method Details [hide private]

server_bind(self)

source code 

Override 'server_bind' to store the server name.

Overrides: SocketServer.TCPServer.server_bind

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test-pysrc.html0000664000076400007640000001646111122067152023420 0ustar stefanstefan qm.test
Package qm :: Package test
[hide private]
[frames] | no frames]

Source Code for Package qm.test

 1  ######################################################################## 
 2  # 
 3  # File:   __init__.py 
 4  # Author: Alex Samuel 
 5  # Date:   2001-03-08 
 6  # 
 7  # Contents: 
 8  #   qm.test module initialization. 
 9  # 
10  # Copyright (c) 2001 by CodeSourcery, LLC.  All rights reserved.  
11  # 
12  # For license terms see the file COPYING. 
13  # 
14  ######################################################################## 
15   
16  ######################################################################## 
17  # imports 
18  ######################################################################## 
19   
20  ######################################################################## 
21  # Local Variables: 
22  # mode: python 
23  # indent-tabs-mode: nil 
24  # fill-column: 72 
25  # End: 
26   

qmtest-2.4.1/share/doc/qmtest/html/manual/qm.executable.Executable-class.html0000664000076400007640000006066011122067146026612 0ustar stefanstefan qm.executable.Executable
Package qm :: Module executable :: Class Executable
[hide private]
[frames] | no frames]

Class Executable

source code

object --+
         |
        Executable

An 'Executable' is a program that the operating system can run.

'Exectuable' (and classes derived from it) create child processes. The 'Spawn' function creates child processes that execute asynchronously. The 'Run' function creates child processes that execute synchrounously, i.e,. the 'Run' function does not return until the child process has completed its execution.

It is safe to reuse a particular 'Executable' instance (by calling 'Spawn' or 'Run' more than once), so long as the uses are not interleaved.

Instance Methods [hide private]
 
Spawn(self, arguments=[], environment=None, dir=None, path=None, exception_pipe=None)
Spawn the program.
source code
 
Run(self, arguments=[], environment=None, dir=None, path=None)
Spawn the program and wait for it to finish.
source code
 
_InitializeParent(self)
Initialize the parent process.
source code
 
Kill(self)
Kill the child process.
source code
 
_HandleChild(self)
Run in the parent process after the child has been created.
source code
 
_InitializeChild(self)
Initialize the child process.
source code
 
_DoParent(self)
Perform actions required in the parent after 'Spawn'.
source code
 
_GetChildPID(self)
Return the process ID for the child process.
source code
 
__CreateCommandLine(self, arguments)
Return a string giving the process command line.
source code

Inherited from object: __delattr__, __getattribute__, __hash__, __init__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __str__

Properties [hide private]

Inherited from object: __class__

Method Details [hide private]

Spawn(self, arguments=[], environment=None, dir=None, path=None, exception_pipe=None)

source code 

Spawn the program.

'arguments' -- The sequence of arguments that should be passed to the executable. The first argument provided in this sequence will be 'argv[0]'; that is also the value used for the path to the executable.

'environment' -- If not 'None', a dictionary giving the environment that should be provided to the child.

'dir' -- If not 'None', the directory in which the child should begin execution. If 'None', the child will execute in the same directory as the parent.

'path' -- If not 'None', the path to the program to run. If 'None', 'arguments[0]' is used.

'exception_pipe' -- If not 'None', a pipe that the child can use to communicate an exception to the parent. This pipe is only used on UNIX systems. The write end of the pipe will be closed by this function.

returns -- The PID of the child.

Before creating the child, the parent will call 'self._InitializeParent'. On UNIX systems, the child will call 'self._InitializeChild' after 'fork', but before 'exec'. On non-UNIX systems, 'self._InitializeChild' will never be called.

After creating the child, 'self._HandleChild' is called in the parent. This hook should be used to handle tasks that must be performed after the child is running.

If the path to the program is absolute, or contains no separator characters, it is not modified. Otherwise the path to the program is relative, it is transformed into an absolute path using 'dir' as the base, or the current directory if 'dir' is not set.

Run(self, arguments=[], environment=None, dir=None, path=None)

source code 

Spawn the program and wait for it to finish.

'arguments' -- The sequence of arguments that should be passed to the executable. The first argument provided in this sequence will be 'argv[0]'.

'environment' -- If not 'None', a dictionary giving the environment that should be provided to the child. If 'None', the child will inherit the parents environment.

'dir' -- If not 'None', the directory in which the child should begin execution. If 'None', the child will execute in the same directory as the parent.

'path' -- If not 'None', the path to the program to run. If 'None', 'arguments[0]' is used.

returns -- The status returned by the program. Under UNIX, this is the value returned by 'waitpid'; under Windows, it is the value returned by 'GetExitCodeProcess'.

After invoking 'Spawn', this function invokes '_DoParent' to allow the parent process to perform whatever actions are required. After that function returns, the parent waits for the child process to exit.

_InitializeParent(self)

source code 

Initialize the parent process.

Before spawning the child, this method is invoked to give the parent a chance to initialize itself.

returns -- Under Windows, a 'PySTARTUPINFO' structure explaining how the child should be initialized. On other systems, the return value is ignored.

Kill(self)

source code 

Kill the child process.

The child process is killed in a way that does not permit an orderly shutdown. In other words, 'SIGKILL' is used under UNIX, not 'SIGTERM'. On Windows, 'TerminateProcess' is used, and the exit code from the child process will be '1'.

_HandleChild(self)

source code 

Run in the parent process after the child has been created.

The child process has been spawned; its PID is avialable via '_GetChildPID'. Take any actions in the parent that are required now that the child exists.

Derived class versions must call this method.

_InitializeChild(self)

source code 

Initialize the child process.

After 'fork' is called this method is invoked to give the child a chance to initialize itself. '_InitializeParent' will already have been called in the parent process.

This method is not used under Windows.

_GetChildPID(self)

source code 

Return the process ID for the child process.

returns -- The process ID for the child process. (On Windows, the value returned is the process handle.) Returns 'None' if the child has not yet been created, or if something went awry when creating it. For example, if 'os.fork' throws an exception, this value will return 'None'.

__CreateCommandLine(self, arguments)

source code 

Return a string giving the process command line.

arguments -- A sequence of arguments (including argv[0]) indicating the command to be run.

returns -- A string that could be provided to the shell in order to run the command.


qmtest-2.4.1/share/doc/qmtest/html/manual/identifier-index-Q.html0000664000076400007640000002027511122067144024313 0ustar stefanstefan Identifier Index
 
[hide private]
[frames] | no frames]

Identifier Index

[ A B C D E F G H I J K L M N O P Q R S T U V W X Y Z _ ]

Q



qmtest-2.4.1/share/doc/qmtest/html/manual/qm.dist.command.install_extensions-pysrc.html0000664000076400007640000012377611122067163030757 0ustar stefanstefan qm.dist.command.install_extensions
Package qm :: Package dist :: Package command :: Module install_extensions
[hide private]
[frames] | no frames]

Source Code for Module qm.dist.command.install_extensions

  1  ######################################################################## 
  2  # 
  3  # File:   install_extensions.py 
  4  # Author: Stefan Seefeld 
  5  # Date:   2005-11-16 
  6  # 
  7  # Contents: 
  8  #   Command to install qmtest extensions. 
  9  # 
 10  # Copyright (c) 2005 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm.xmlutil 
 21  from distutils.command.install_lib import install_lib 
 22  import os, dircache, xml 
 23   
 24  ######################################################################## 
 25  # Classes 
 26  ######################################################################## 
 27   
28 -def _compare_files(a, b):
29 """Compare the content of two files. 30 31 'a' -- Filename of first file to be compared. 32 33 'b' -- Filename of second file to be compared. 34 35 returns -- True if both files have the same content, False otherwise.""" 36 37 file_a, file_b = open(a, 'r'), open(b, 'r') 38 for line in file_a: 39 if line != file_b.readline(): 40 return False 41 if file_b.readline(): 42 return False 43 return True
44 45
46 -class install_extensions(install_lib):
47 """Install extension files.""" 48 49 description = "install qmtest extension classes." 50 51
52 - def finalize_options(self):
53 54 if not self.install_dir: 55 i = self.distribution.get_command_obj('install') 56 i.ensure_finalized() 57 prefix = i.root or i.prefix 58 self.install_dir = os.path.join(prefix, qm.extension_path) 59 install_lib.finalize_options(self) 60 61 b = self.distribution.get_command_obj('build_extensions') 62 b.ensure_finalized() 63 self.build_dir = b.build_dir
64 65
66 - def run(self):
67 68 # Make sure we have built everything we need first 69 self.run_command('build_extensions') 70 71 if not os.path.isdir(self.install_dir): 72 self.mkpath(self.install_dir) 73 if not os.path.exists(os.path.join(self.install_dir, 'classes.qmc')): 74 # This is the first time extensions are installed there. 75 self.copy_tree(self.build_dir, self.install_dir) 76 else: 77 # Test that to-be-copied modules don't overwrite existing ones: 78 old_files = [f for f in dircache.listdir(self.install_dir) 79 if f.endswith('.py')] 80 new_files = [f for f in dircache.listdir(self.build_dir) 81 if f.endswith('.py') and f != '__init__.py'] 82 overlap = [] 83 for f in new_files: 84 if f in old_files: 85 # Don't complain if both files are identical. 86 if not _compare_files(os.path.join(self.build_dir, f), 87 os.path.join(self.install_dir, f)): 88 overlap.append(f) 89 if overlap: 90 print "Error: The following extension files already exist:" 91 for o in overlap: 92 print " %s"%o 93 return 94 # Copy all modules to the install directory. 95 for f in new_files: 96 self.copy_file(os.path.join(self.build_dir, f), 97 os.path.join(self.install_dir, f), 98 preserve_mode=0) 99 100 # Carefully merge the new extensions into an existing repository. 101 old_qmc = qm.xmlutil.load_xml_file(os.path.join(self.install_dir, 102 'classes.qmc')) 103 old_root = old_qmc.documentElement 104 105 new_qmc = qm.xmlutil.load_xml_file(os.path.join(self.build_dir, 106 'classes.qmc')) 107 new_root = new_qmc.documentElement 108 109 for ext in new_root.getElementsByTagName("class"): 110 # If this entry already exists in the repository, skip it. 111 name = ext.getAttribute("name") 112 entries = [c for c in old_root.childNodes 113 if c.nodeType == xml.dom.Node.ELEMENT_NODE and 114 c.tagName == "class" and 115 c.getAttribute("name") == name] 116 if not entries: 117 old_root.appendChild(ext) 118 old_root.appendChild(old_qmc.createTextNode('\n')) 119 # Write new repository file. 120 old_qmc.writexml(open(os.path.join(self.install_dir, 121 'tmp-classes.qmc'), 'w')) 122 # If that worked, update the original one. 123 os.rename(os.path.join(self.install_dir, 'tmp-classes.qmc'), 124 os.path.join(self.install_dir, 'classes.qmc'))
125

qmtest-2.4.1/share/doc/qmtest/html/manual/toc-qm.test.base-module.html0000664000076400007640000000567411122067144025246 0ustar stefanstefan base

Module base


Classes

CouldNotLoadExtensionError

Functions

get_extension_class
get_extension_class_from_directory
get_extension_class_names
get_extension_class_names_in_directory
get_extension_classes
get_extension_directories
get_resource_class
get_test_class
load_expectations
load_outcomes
load_results

Variables

extension_kinds

[hide private] qmtest-2.4.1/share/doc/qmtest/html/manual/qm.extension-module.html0000664000076400007640000006717711122067145024616 0ustar stefanstefan qm.extension
Package qm :: Module extension
[hide private]
[frames] | no frames]

Module extension

source code

Classes [hide private]
  Extension
A class derived from 'Extension' is a QM extension.
Functions [hide private]
 
get_class_arguments(extension_class)
Return the arguments associated with 'extension_class'.
source code
 
get_class_arguments_as_dictionary(extension_class)
Return the arguments associated with 'extension_class'.
source code
 
get_class_description(extension_class, brief=0)
Return a brief description of the extension class 'extension_class'.
source code
 
get_extension_class_name(extension_class)
Return the name of 'extension_class'.
source code
 
validate_arguments(extension_class, arguments)
Validate the 'arguments' to the 'extension_class'.
source code
 
make_dom_element(extension_class, arguments, document, element=None)
Create a DOM node for an instance of 'extension_class'.
source code
 
make_dom_document(extension_class, arguments)
Create a DOM document for an instance of 'extension_class'.
source code
 
write_extension_file(extension_class, arguments, file)
Write an XML description of an extension to 'file'.
source code
 
parse_dom_element(element, class_loader, attachment_store=None)
Parse a DOM node representing an instance of 'Extension'.
source code
 
read_extension_file(file, class_loader, attachment_store=None)
Parse a file describing an extension instance.
source code
 
parse_descriptor(descriptor, class_loader, extension_loader=None)
Parse a descriptor representing an instance of 'Extension'.
source code
Function Details [hide private]

get_class_arguments(extension_class)

source code 

Return the arguments associated with 'extension_class'.

'extension_class' -- A class derived from 'Extension'.

returns -- A list of 'Field' objects containing all of the arguments in the class hierarchy.

get_class_arguments_as_dictionary(extension_class)

source code 

Return the arguments associated with 'extension_class'.

'extension_class' -- A class derived from 'Extension'.

returns -- A dictionary mapping argument names to 'Field' objects. The dictionary contains all of the arguments in the class hierarchy.

get_class_description(extension_class, brief=0)

source code 

Return a brief description of the extension class 'extension_class'.

'extension_class' -- A class derived from 'Extension'.

'brief' -- If true, return a brief (one-line) description of the extension class.

returns -- A structured text description of 'extension_class'.

get_extension_class_name(extension_class)

source code 

Return the name of 'extension_class'.

'extension_class' -- A class derived from 'Extension'.

returns -- The name of 'extension_class'. This is the name that is used when users refer to the class.

validate_arguments(extension_class, arguments)

source code 

Validate the 'arguments' to the 'extension_class'.

'extension_class' -- A class derived from 'Extension'.

'arguments' -- A dictionary mapping argument names (strings) to values (strings).

returns -- A dictionary mapping 'Field's to values.

Check that each of the 'arguments' is a valid argument to 'extension_class'. If so, the argumets are converted as required by the 'Field', and the dictionary returned contains the converted values. Otherwise, an exception is raised.

make_dom_element(extension_class, arguments, document, element=None)

source code 

Create a DOM node for an instance of 'extension_class'.

'extension_class' -- A class derived from 'Extension'.

'arguments' -- The arguments to the extension class.

'document' -- The DOM document that will contain the new element.

'element' -- If not 'None' the extension element to which items will be added. Otherwise, a new element will be created by this function.

returns -- A new DOM element corresponding to an instance of the extension class. The caller is responsible for attaching it to the 'document'.

make_dom_document(extension_class, arguments)

source code 

Create a DOM document for an instance of 'extension_class'.

'extension_class' -- A class derived from 'Extension'.

'arguments' -- The arguments to the extension class.

returns -- A new DOM document corresponding to an instance of the extension class.

write_extension_file(extension_class, arguments, file)

source code 

Write an XML description of an extension to 'file'.

'extension_class' -- A class derived from 'Extension'.

'arguments' -- A dictionary mapping argument names to values.

'file' -- A file object to which the data should be written.

parse_dom_element(element, class_loader, attachment_store=None)

source code 

Parse a DOM node representing an instance of 'Extension'.

'element' -- A DOM node, of the format created by 'make_dom_element'.

'class_loader' -- A callable. The callable will be passed the name of the extension class and must return the actual class object.

'attachment_store' -- The 'AttachmentStore' in which attachments can be found.

returns -- A pair ('extension_class', 'arguments') containing the extension class (a class derived from 'Extension') and the arguments (a dictionary mapping names to values) stored in the 'element'.

read_extension_file(file, class_loader, attachment_store=None)

source code 

Parse a file describing an extension instance.

'file' -- A file-like object from which the extension instance will be read.

'class_loader' -- A callable. The callable will be passed the name of the extension class and must return the actual class object.

'attachment_store' -- The 'AttachmentStore' in which attachments can be found.

returns -- A pair ('extension_class', 'arguments') containing the extension class (a class derived from 'Extension') and the arguments (a dictionary mapping names to values) stored in the 'element'.

parse_descriptor(descriptor, class_loader, extension_loader=None)

source code 

Parse a descriptor representing an instance of 'Extension'.

'descriptor' -- A string representing an instance of 'Extension'. The 'descriptor' has the form 'class(arg1 = "val1", arg2 = "val2", ...)'. The arguments and the parentheses are optional.

'class_loader' -- A callable that, when passed the name of the extension class, will return the actual Python class object.

'extension_loader' -- A callable that loads an existing extension given the name of that extension and returns a tuple '(class, arguments)' where 'class' is a class derived from 'Extension'. If 'extension_loader' is 'None', or if the 'class' returned is 'None', then if a file exists named 'class', the extension is read from 'class' as XML. Any arguments returned by the extension loader or read from the file system are overridden by the arguments explicitly provided in the descriptor.

returns -- A pair ('extension_class', 'arguments') containing the extension class (a class derived from 'Extension') and the arguments (a dictionary mapping names to values) stored in the 'element'. The 'arguments' will have already been processed by 'validate_arguments' by the time they are returned.


qmtest-2.4.1/share/doc/qmtest/html/manual/qm.test.command_thread-pysrc.html0000664000076400007640000020260111122067154026357 0ustar stefanstefan qm.test.command_thread
Package qm :: Package test :: Module command_thread
[hide private]
[frames] | no frames]

Source Code for Module qm.test.command_thread

  1  ######################################################################## 
  2  # 
  3  # File:   command_thread.py 
  4  # Author: Mark Mitchell 
  5  # Date:   01/02/2002 
  6  # 
  7  # Contents: 
  8  #   CommandThread 
  9  # 
 10  # Copyright (c) 2002 by CodeSourcery, LLC.  All rights reserved.  
 11  # 
 12  # For license terms see the file COPYING. 
 13  # 
 14  ######################################################################## 
 15   
 16  ######################################################################## 
 17  # Imports 
 18  ######################################################################## 
 19   
 20  import qm 
 21  import Queue 
 22  from   threading import * 
 23  import sys 
 24  import types 
 25   
 26  ######################################################################## 
 27  # Classes 
 28  ######################################################################## 
 29   
30 -class CommandThread(Thread):
31 """A 'CommandThread' is a thread that executes commands. 32 33 The commands are written to a 'Queue' by a controlling thread. 34 The 'CommandThread' extracts the commands and dispatches them to 35 derived class methods that process them. This class is used as a 36 base class for thread classes used by some targets. 37 38 The commands are written to the 'Queue' as Python objects. The 39 normal commands have the form '(method, descriptor, context)' 40 where 'method' is a string. At present, the only value used for 41 'method' is '_RunTest'. In that case 'descriptor' is a test 42 descriptor and 'context' is a 'Context'. The 'Stop' command is 43 provided as a simple string, not a tuple.""" 44
45 - def __init__(self, target):
46 """Construct a new 'CommandThread'. 47 48 'target' -- The 'Target' that owns this thread.""" 49 50 Thread.__init__(self, None, None, None) 51 52 # Remember the target. 53 self.__target = target 54 55 # Create the queue to which the controlling thread will 56 # write commands. 57 self.__command_queue = Queue.Queue(0)
58 59
60 - def run(self):
61 """Execute the thread.""" 62 63 try: 64 # Process commands from the queue, until the "quit" 65 # command is received. 66 while 1: 67 # Read the command. 68 command = self.__command_queue.get() 69 70 # If the command is just a string, it should be 71 # the 'Stop' command. 72 if isinstance(command, types.StringType): 73 assert command == "Stop" 74 self._Trace("Received stop command") 75 self._Stop() 76 break 77 78 # Decompose command. 79 method, desc, context = command 80 assert method == "_RunTest" 81 # Run it. 82 self._Trace("About to run test " + desc.GetId()) 83 self._RunTest(desc, context) 84 self._Trace("Finished running test " + desc.GetId()) 85 except: 86 # Exceptions should not occur in the above loop. However, 87 # in the event that one does occur it is easier to debug 88 # QMTest is the exception is written out. 89 exc_info = sys.exc_info() 90 sys.stderr.write(qm.common.format_exception(exc_info)) 91 assert 0
92 93
94 - def GetTarget(self):
95 """Return the 'Target' associated with this thread. 96 97 returns -- The 'Target' with which this thread is associated. 98 99 Derived classes must not override this method.""" 100 101 return self.__target
102 103
104 - def RunTest(self, descriptor, context):
105 """Run the test given by 'descriptor'. 106 107 'descriptor' -- The 'TestDescriptor' for the test to be run. 108 109 'context' -- The 'Context' in which to run the test. 110 111 This method is called by the controlling thread. 112 113 Derived classes must not override this method.""" 114 115 self.__command_queue.put(("_RunTest", descriptor, context))
116 117
118 - def Stop(self):
119 """Stop the thread. 120 121 Derived classes must not override this method.""" 122 123 self.__command_queue.put("Stop")
124 125
126 - def _RunTest(self, descriptor, context):
127 """Run the test given by 'descriptor'. 128 129 'descriptor' -- The 'TestDescriptor' for the test to be run. 130 131 'context' -- The 'Context' in which to run the test. 132 133 Derived classes must override this method.""" 134 135 raise NotImplementedError
136 137
138 - def _Stop(self):
139 """Stop the thread. 140 141 This method is called in the thread after 'Stop' is called 142 from the controlling thread. Derived classes can use this 143 method to release resources before the thread is destroyed. 144 145 Derived classes may override this method.""" 146 147 pass
148 149
150 - def _Trace(self, message):
151 """Write a trace 'message'. 152 153 'message' -- A string to be output as a trace message.""" 154 155 if __debug__: 156 tracer = qm.test.cmdline.get_qmtest().GetTracer() 157 tracer.Write(message, "command_thread")
158

qmtest-2.4.1/share/doc/qmtest/html/tutorial/0000775000076400007640000000000011122067201020352 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/html/tutorial/command-create-tdb.html0000664000076400007640000001236411122066676024713 0ustar stefanstefan4.qmtest create-tdb

4.qmtest create-tdb

4.1.Summary

Create a new test database.

4.2.Synopsis

qmtest create-tdb [ option ...]

4.3.Description

The qmtest create-tdb command creates a new, empty test database. A test database is a directory in which QMTest stores configuration files, tests, and other data. Certain test database classes may also store data elsewhere, such as in an external relational database.

The test database is created in the directory specified by --tdb (-D) option or by setting the QMTEST_DB_PATH environment variable. If no database path is specified, QMTest assumes that the current directory is the test database.

By default, QMTest creates a new test database that uses the standard XML-based implementation. (See Section5, “Writing Database Classes” for information about writing a test database class.)

The create-tdb command accepts these options:

-a name=value, --attribute name=value

Set the database attribute name to value. The set of attribute names and valid values is dependent on the database class in use. The default database class accepts no attributes.

-c class, --class class

Use the test database class given by class. The class may have the general form described in Section2, “qmtest create. Once you create a test database, you cannot change the test database implementation it uses. If you do not use this option, QMTest will use the default test database implementation, which uses an XML file format to store tests.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/extending-test-classes.html0000664000076400007640000001405711122066700025647 0ustar stefanstefan3.Writing Test Classes

3.Writing Test Classes

If the test classes that come with QMTest do not serve your needs, you can write a new test class. A test class is a Python class derived from Test, which itself is derived from Extension. It may define parameters as discussed in Section1, “Extension Classes”. The test class must provide a Run method that implements the way the test is performed and results are validated.

For example, if you want to test that a compiler correctly compiled a particular source file, the source file would be an argument to the test while the Run method would be responsible for running the compiler and the program generated by the compiler. The path to the compiler itself would be provided via the context ( Section6, “Context”); that is an input to the testing system that varies depending on the user's environment.

The Run method takes two arguments: the context and the result. The context object is an instance of Context. The result object is an instance of Result. The result is initialized with the PASS outcome. Therefore, if the Run method does not modify the result, the test will pass. If the test fails, the Result.Fail method should be called to indicate failure.

The Result.Annotate method can be used to add information to the Result, whether or not the test passes. For example, annotations can be used to record the time a test took to execute, or to log the output from a command run as part of the test. Every annotation is a key/value pair. Both keys and values are strings. The key created by a test class C should have the form C.key_name. The value must be valid HTML. When results are displayed in the GUI, the HTML is presented directly to the user. When results are displayed as text, the HTML is converted to plain text. That conversion uses textual devices (such as single quotes around verbatim text) to emulate the HTML markup where possible.

As a convenience, you can use Python's dictionary notation to access annotations. For example:

    result["C.key1"] = "value"
    result["C.key2"] = result["C.key1"].upper()

  

is equivalent to:

    result.Annotate({ "C.key1" : "value"
                      "C.key2" : "VALUE" })

  

The context (like the result) is a set of key/value pairs. The keys used by a test class C should have the form C.key_name. The values are generally strings, but if a test depends on a resource, the resource can provide context values that are not strings.

If the Run raises an unhandled exception, QMTest creates a result for the test with the outcome ERROR. Therefore, test classes should be designed so that they do not raise unhandled exceptions when a test fails. However, QMTest handles the exception generated by the use of non-existant context variables specially. Because this situation generally indicates incorrect usage of the test suite, QMTest uses a special error message that instructs the user to supply a value for the context variable.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-run.html0000664000076400007640000003365411122066676023512 0ustar stefanstefan10.qmtest run

10.qmtest run

10.1.Summary

Run tests or test suites.

10.2.Synopsis

qmtest run [ option ...] [ test-name | suite-name ...]

10.3.Description

The qmtest run command runs tests and displays the results. If no test or suite names are specified, QMTest runs all of the tests in the test database. If test or suite names are specified, only those tests or suites are run. Tests listed more than once (directly or by inclusion in a test suite) are run only once.

The run command accepts these options:

-a name=value , --annotate name=value

Annotate the test run by inserting the named annotation name with the value value into all result streams.

This option may be specified multiple times.

-c name=value , --context name=value

Add a property to the test execution context. The name of the property is name, and its value is set to the string value.

This option may be specified multiple times.

-C file, --load-context file

Read properties for the test execution context from the file file.

The file should be a text file with one context property on each line, in the format name=value. Leading and trailing whitespace on each line are ignored. Also, blank lines and lines that begin with "#" (a hash mark) are ignored as comments.

This option may be specified more than once, and used in conjunction with the --context option. All of the context properties specified are added to the eventual context. If a property is set more than once, the last value provided is the one used.

If this option is not specified, but a file named context exists in the current directory, that file is read. The properties specified in this file are processed first; the values in this file can be overridden by subsequent uses of the --context option on the command line.

-f format, --format format

Control the format used when displaying results. The format specified must be one of full, brief, stats, batch, or none. The brief format is the default if QMTest was invoked interactively; the batch format is the default otherwise. In the full format, QMTest displays any annotations provided in test results. In the brief mode only the causes of failures are shown; detailed annotations are not shown. In the stats format, no details about failing tests are displayed; only statistics showing the number of passing and failing tests are displayed. In the batch mode, the summary is displayed first, followed by detailed results for tests with unexpected outcomes. In the none mode, no results are displayed, but a results file is still created, unless the --no-output option is also provided.

-j count, --concurrency count

Run tests in multiple count concurrent processes on the local computer. On multiprocessor machines, the processes may be scheduled to run in parallel on different processors. QMTest automatically collects results from the processes and presents combines test results and summary. By default, one process is used.

This option may not be combined with the --targets (-T) option.

--no-output

Do not produce a test results file.

-o file, --output file

Write full test results to file, in QMTest's machine-readable file format. Use a "-" (a hyphen) to write results to the standard output. If neither this option nor --no-output is specified, the results are written to the file named results.qmr in the current directory.

-O file, --outcomes file

Treat file as a set of expected outcomes. The file is usually a results file created either by using the qmtest run or by saving results in the graphical user interface. If file does not appear to be such a file, it is interpreted as an extension descriptor, as described in Section2, “qmtest create. QMTest will expect the results of the current test run to match those specified in the file and will highlight differences from those results.

--random

Run the tests in a random order.

This option can be used to find hidden dependencies between tests in the testsuite. (You may not notice the dependencies if you always run the tests in the same order.)

--rerun file

Rerun only those tests that had unexpected outcomes.

The tests run are determined as follows. QMTest starts with all of the tests specified on the command line, or, if no tests are explicitly specified, all of the tests in the database. If no expectations file is specified (see the description of the --outcomes option), then all tests that passed in the results file indicated by the --rerun option are removed form the set of eligible tests. If an expectations file is specified, then the tests removed are tests whose outcome in the results file indicated by the --rerun option is the same as in the expectations file.

The --rerun provides a simple way of rerunning failing tests. If you run your tests and notice failures, you might try to fix those failing tests. Then, you can rerun the failing tests to see if you succeeded by using the --rerun option.

--result-stream descriptor

Specify an additional output result stream. The descriptor is in the format described in Section2, “qmtest create.

--seed integer

If the --random is used, QMTest randomizes the order in which tests are run, subject to the constraints described in Section1.3, “Ordering and Dependencies”. By default, the random number generator is seeded using the system time.

For debugging purposes, it is sometimes necessary to obtain a reproducible sequence of tests. Use the --seed option to specify the seed for the random number generator.

Note that even with the same random number seed, if tests are run in parallel, scheduling uncertainty may still produce variation in the order in which tests are run.

-T file, --targets file

Use targets specified in target specification file file. If this option is not present, the QMTest/targets in the test database directory will be used. If that file is not present, the tests will be run in serial on the local machine.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-report.html0000664000076400007640000000747011122066676024216 0ustar stefanstefan12.qmtest report

12.qmtest report

12.1.Summary

The qmtest report generates an xml report from a set of test result files.

12.2.Synopsis

qmtest report [-o output] [-f] [ report-file [-e expectation-file] ...]

12.3.Description

The qmtest report extracts information stored in one or more result files and generates an xml report file from it. This report file is then typically processed using xslt to generate html or pdf versions of the report.

The report command accepts the following options:

-f, --flat

Generate a flat listing of test results, instead of reproducing the database directory tree in the report.

-o output file, --output output-file

The name of the file to write the report into.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-hosts.html0000664000076400007640000001150411122066677024772 0ustar stefanstefan8.Hosts

8.Hosts

A number of test classes delegate the execution of executables to a dedicated Host class, for example to allow parts of the test to be run on a different platform (such as when cross-compiling and cross-testing). To achieve that, a number of Host subclasses are provided that can be used to execute code in different ways. Typically, a test class will query the Host instance to use from a context variable.

8.1.local_host.LocalHost

A LocalHost is the machine on which Python is running.

8.2.ssh_host.SSHHost

An SSHHost is accessible via ssh or a similar program. The SSHHost host uses the following parameters.

host_name (text field)

The name of the remote host.

ssh_program (text field)

The path to the remote shell program.

ssh_args (set field)

The arguments to the remote shell program.

scp_program (text field)

The path to the remote copy program.

scp_args (set field)

The arguments to the remote copy program.

default_dir (text field)

The default directory on the remote system.

8.3.ssh_host.RSHHost

An RSHHost is a SSHHost that uses rsh instead of ssh.

8.4.simulator.Simulator

A Simulator is a semi-hosted simulation environment. The Simulator host uses the following parameters.

simulator (text field)

The simulation program.

simulator_args (set field)

Arguments to the simulation program.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-result-streams.html0000664000076400007640000000726411122066677026634 0ustar stefanstefan9.Result Streams and Result Readers

9.Result Streams and Result Readers

Result streams and result readers are the means that allow QMTest to externalize and internalize test results.

9.1.text_result_stream.TextResultStream

A TextResultStream displays information textually, in human readable form. It is used when QMTest is run without a graphical user interface.

9.2.xml_result_stream.XMLResultStream

An XMLResultStream writes out results as XML. The resulting file can be read back in using an XMLResultReader.

9.3.pickle_result_stream.PickleResultStream

A PickleResultStream writes out results as Python pickles. The resulting file can be read back in using a PickleResultReader.

9.4.sql_result_stream.SQLResultStream

An SQLResultStream writes results out to an SQL database. To read results from an SQL database use SQLResultReader.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts-test-database.html0000664000076400007640000000622311122066675025616 0ustar stefanstefan4.Test Database

4.Test Database

A test database stores tests, test suites, and other entities. When you ask QMTest for a particular test by name, it queries the test database to obtain the test itself. QMTest stores a test database in a single directory, which may include many files and subdirectories.

In general, QMTest can only use one test database at a time. However, it is possible to create a test database which contains other test databases. This mechanism allows you to store the tests associated with different parts of a large application in different test databases, and still combine them into a single large test database when required.

A single test database can store many different kinds of tests. By default, QMTest stores tests, test suites, and all other entities in the test database using subdirectories containing XML files. Generally, there should be no need to examine or modify these files directly. However, the use of an XML format makes it easy for you to automatically generate tests from another program, if required.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/reference-return-value.html0000664000076400007640000000567411122066677025661 0ustar stefanstefan15.Return Value

15.Return Value

If QMTest successfully performed the action requested, QMTest returns 0. For the qmtest run or qmtest summarize commands, success implies not only that the tests ran, but also that all of the tests passed (if the --outcomes option was not used) or had their expected outcomes (if the --outcomes option was used).

If either the run command or the summarize command was used, and at least one test failed (if the --outcomes option was not used) or had an unexpected outcome (if the --outcomes option was used), qmtest returns 1.

If QMTest could not perform the action requested, qmtest returns 2.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-extensions.html0000664000076400007640000000751511122066676025102 0ustar stefanstefan6.qmtest extensions

6.qmtest extensions

6.1.Summary

List available extension classes.

6.2.Synopsis

qmtest extensions [ option ...]

6.3.Description

The qmtest extensions lists available extension classes and provides a brief description of each class. You can use this command to list all of the available extension classes, or to list all of the available extension classes of a particular type. For example, you can use this command to list all of the available test classes.

The extensions command accepts these options:

-k kind , --kind kind

List the available extension classes of the indicated kind. The kind must be one of test, resource, target, database, host, or run_database.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts-test-results.html0000664000076400007640000001413511122066675025554 0ustar stefanstefan2.Test Results

2.Test Results

A result is an outcome together with some annotations. The outcome indicates whether the test passed or failed. The annotations give additional information about the result, such as the manner in which the test failed, the output the test produced, or the amount of time it took to run the test.

2.1.Outcomes

The outcome of a test indicates whether it passed or failed, or whether some exceptional event occurred. There are four test outcomes:

  • PASS: The test succeeded.

  • FAIL: The test failed.

  • ERROR: A problem occurred in the test execution environment, rather than in the tested system. For example, this outcome is used when the test class attempted to run an executable in order to test it, but could not because the system call to create a new process failed.

    This outcome may also indicate a defect in QMTest or in the test class.

  • UNTESTED: QMTest did not attempt to execute the test. For example, this outcome is used when QMTest determines that a prerequisite test failed.

Thus, running QMTest with the two previously defined tests will result in the following output:

> qmtest run
...
--- TEST RESULTS -------------------------------------------------------------

  python_fail                                   : FAIL
    Expression evaluates to false.

  python_pass                                   : PASS

...
--- STATISTICS ---------------------------------------------------------------

       2        tests total
       1 ( 50%) tests FAIL
       1 ( 50%) tests PASS
      

In addition, the results are stored in a results file (results.qmr by default).

2.2.Annotations

An annotation is a key/value pair. Both the keys and values are strings. The value is HTML. When a test (or resource) runs it may add annotations to the result. These annotations are displayed by QMTest and preserved in the results file. If you write your own test class, you can use annotations to store information that will make your test class more informative.

2.3.Expected Outcomes

The easiest way to create expectations is to tell QMTest that you expect future results to be the same as the results you just obtained. Thus, QMTest accepts result files obtained from prior test runs as expectations.

Thus, rerunning QMTest, but using results.qmr as expectations, the test results are displayed differently:

> qmtest run -O results.qmr
...
--- TEST RESULTS -------------------------------------------------------------

  python_fail                                   : XFAIL
    Expression evaluates to false.

  python_pass                                   : PASS

...
--- TESTS WITH UNEXPECTED OUTCOMES -------------------------------------------

  None.


--- STATISTICS ---------------------------------------------------------------

       2 (100%) tests as expected

    
qmtest-2.4.1/share/doc/qmtest/html/tutorial/reference-env-vars.html0000664000076400007640000000576411122066676024770 0ustar stefanstefan13.Environment Variables

13.Environment Variables

QMTest recognizes the following environment variables:

QMTEST_CLASS_PATH

If this environment variable is set, it should contain a list of directories in the same format as used for the system's PATH environment variable. These directories are searched (before the directories that QMTest searches by default) when looking for extension classes such as test classes and database classes.

QMTEST_DB_PATH

If this environment variable is set, its value is used as the location of the test database, unless the --tdb (-D) option is used. If this environment variable is not set and the --tdb option is not used, the current directory is used as the test database.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/extending-registering.html0000664000076400007640000001034411122066700025552 0ustar stefanstefan6.Registering and Distributing Extension Classes

6.Registering and Distributing Extension Classes

To use your Extension class, you must place the Python module file containing it in a directory where QMTest can find it. QMTest searches for extensions in particular places, in the following order:

  1. in the paths contained in the QMTEST_CLASS_PATH environment variable.

  2. in the class-path associated with a particular test database (typically the QMTest/ subdirectory).

  3. in the site-extension path associated with a particular QMTest installation.

  4. in the set of built-in extensions that come with a particular QMTest installation.

You should generally place module files containing extension classes in the test database's QMTest directory, unless you plan to use the test classes in more than one test database.

You must use the qmtest register command to register your new extension class. You must perform this step no matter where you place the module containing your extension class.

You can refer to the new extension class using the syntax module.Class, where module is the name of the module and Class is the name of the class.

To make your extension classes sharable by other test database instances, you should install them into the site-extension path associated with a qmtest installation.

To facilitate this installation, QMTest provides code that can be used in conjunction with python's distutils to install, and even distribute them. The following setup.py script will allow you to install (and even package !) all extension modules from the extensions subdirectory:

from qm.dist.distribution import Distribution
from distutils.core import setup

setup(distclass=Distribution,
      qmtest_extensions="extensions")
  

Then, the following command installs extension modules from extensions:

> python setup.py install
  
qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-describe.html0000664000076400007640000001010411122066676024447 0ustar stefanstefan7.qmtest describe

7.qmtest describe

7.1.Summary

Describe an extension class.

7.2.Synopsis

qmtest describe [ option ...] kind name

7.3.Description

The qmtest describe displays a description of the extension name.

The describe command accepts these options:

--kind kind

Describe an extension class of the indicated kind. The kind must be one of test, resource, target, database, host, or run_database.

-l, --long

Provide a long (i.e. more detailed detailed) description of the extension.

-a name, --attribute name

Describe the given attribute.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-test-targets.html0000664000076400007640000002567211122066677026273 0ustar stefanstefan7.Test Targets

7.Test Targets

Test targets represent entities that QMTest uses to run tests. See Section8, “Targets” for an overview of how QMTest uses targets.

7.1.Target Specification

Each target specification includes the following:

  1. The name of the target. This is a name identifying the target, such as the host name of the computer which will run the tests. Target names should be unique in a single target file.

  2. The target class. Similar to a test class, a target class is a Python class which implements a type of target. As with test classes, a target class is identified by its name, which includes the module name and the class name.

    For example, thread_target.ThreadTarget is the name of a target class, provided by QMTest, which runs tests in multiple threads on the local computer.

    QMTest includes several target class implementations. See Section7.2, “Target Classes” for details.

  3. A target group name. The test implementor may choose the syntax of target group names in a test implementation. Target groups may be used to encode information about target attributes, such as architecture and operating system, and capabilities.

  4. Optionally, a target specification may include additional properties. Properties are named and have string values. Some target classes may use property information to control their configuration. For instance, a target class which executes tests on a remote computer would extract the network address of the remote computer from a target property.

7.2.Target Classes

QMTest includes these target class implementations.

7.2.1.SerialTarget

The serial_target.SerialTarget target class runs tests one after the other on the machine running QMTest. If you use a SerialTarget, you should not also use any other targets, including another SerialTarget at the same time.

7.2.2.ThreadTarget

The thread_target.ThreadTarget target class runs tests in one or more threads on the machine running QMTest. The ThreadTarget can be used to run multiple tests at once.

ThreadTarget uses the following properties:

  • The concurrency specifies the number of threads to use. Larger numbers of threads will allow QMTest to run more tests in parallel. You can experiment with this value to find the setting that allows QMTest to run tests most quickly.

7.2.3.ProcessTarget

The process_target.ProcessTarget target class run tests in one more processes on the machine running QMTest. This target class is not available on Windows. Like ThreadTarget, ProcessTarget can be used to run multiple tests simultaneously.

In general, you should use ThreadTarget instead of ProcessTarget to maximize QMTest performance. However, on machines that do not have threads, ProcessTarget provides an alternative way of running tests in parallel.

ProcessTarget uses the following properties:

  • The concurrency specifies the number of processes to use. Larger numbers of processes will allow QMTest to run more tests in parallel. You can experiment with this value to find the setting that allows QMTest to run tests most quickly.

  • QMTest uses the path given by the qmtest property to create additional QMTest instances. By default, the path /usr/local/bin/qmtest is used.

7.2.4.RemoteShellTarget

The rsh_target.RSHTarget target class runs tests on a remote computer via a remote shell invocation (rsh, ssh, or similar). This target uses a remote shell to invoke a program similar to the qmtest command on the remote computer. This remote program accepts test commands and responds with results from running these tests.

To use RSHTarget, the remote computer must have QMTest installed and must contain an identical copy of the test database. QMTest does not transfer entire tests over the remote shell connection; instead, it relies on the remote test database for loading tests.

In addition, the remote shell program must be configured to allow a remote login without additional intervention (such as typing a password). If you use rsh, you can use an .rhosts file to set this up. If you use ssh, you can use an SSH public key and the ssh-agent program for this. See the corresponding manual pages for details.

RSHTarget uses all of the properties given above for ProcessTarget. In addition, RSHTarget uses the following properties:

  • The remote_shell property specifies the path to the remote shell program. The default value is ssh. The remote shell program must accept the same command-line syntax as rsh.

  • The host property specifies the remote host name. If omitted, the target name is used.

  • The database_path property specifies the path to the test database on the remote computer. The test database must be identical to the local test database. If omitted, the local test database path is used.

  • The arguments property specifies additional command-line arguments for the remote shell program. The value of this property is split at space characters, and the arguments are added to the command line before the name of the remote host.

    For example, if you are using the ssh remote shell program and wish to log in to the remote computer using a different user account, specify the -l username option using the arguments property.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/reference-config-file.html0000664000076400007640000000514111122066677025377 0ustar stefanstefan14.Configuration Variables

14.Configuration Variables

These configuration variables are used by QMTest. You should define them in the [qmtest] section of your QM configuration file.

pid-file

The default path to use when creating a PID file with the --pid-file option. (See Section5, “qmtest gui for more information about this option.) If this entry is not present, an appropriate platform-specific default value is used.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/extending-resource-classes.html0000664000076400007640000000740411122066700026515 0ustar stefanstefan4.Writing Resource Classes

4.Writing Resource Classes

Writing resource classes is similar to writing test classes. The requirements are the same except that, instead of a Run method, you must provide two methods named SetUp and CleanUp. The SetUp method must have the same signature as a test classs Run. The CleanUp method is similar, but does not take a context parameter.

The SetUp method may add additional properties to the context by assigning to its context parameter. These additional properties will be visible only to tests that require this resource.

The example below shows the SetUp and CleanUp from the standard QMTest TempDirectoryResource class. This resource creates a temporary directory for use by the tests that depend on the resource. The SetUp method creates the temporary directory and records the path to the temporary directory in the context so that tests know where to find the directory. The CleanUp method removes the temporary directory.

 
 
    def SetUp(self, context, result):

        # Create a temporary directory.
        self.__dir = qm.temporary_directory.TemporaryDirectory()
        # Provide dependent tests with the path to the new directory.
        context["TemporaryDirectoryResource.temp_dir_path"] 
          = self.__dir.GetPath()
    

    def CleanUp(self, result):

        # Remove the temporary directory.
        del self.__dir

  

qmtest-2.4.1/share/doc/qmtest/html/tutorial/cli.html0000664000076400007640000001553611122066677022041 0ustar stefanstefanChapter2.Invoking QMTest

Chapter2.Invoking QMTest

All QMTest functionality is available using the qmtest command.

1.qmtest

1.1.Synopsis

qmtest [ option ...] command [ command-option ...] [ argument ...]

1.2.Options

These options can be used with any QMTest command, and must precede the command name on the command line.

All options are available in a "long form" prefixed with "--" (two hyphens). Some options also may be specified in a "short form" consisting of a single hyphen and a one-letter abbreviation. Short-form options may be combined; for example, -abc is equivalent to -a -b -c.

-D path, --tdb path

Use the test database located in the directory given by path. This flag overrides the value of the environment variable QMTEST_DB_PATH. If neither this flag nor the environment variable is specified, QMTest assumes that the current directory should be used as the database. See Section4, “Test Database”.

-h, --help

Display help information, listing commands and general options for the qmtest command.

--version

Describe the version of QMTest in use.

Additional options are available for specific commands; these are presented with each command. Options specific to a command must follow the command on the command line. Specify the --help (-h) option after the command for a description of the command and a list of of available options for that command.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts-targets.html0000664000076400007640000000733411122066675024552 0ustar stefanstefan8.Targets

8.Targets

A target is QMTest's abstraction of a machine. By using multiple targets, you can run your tests on multiple machines at once. If you have many tests, and many machines, you can greatly reduce the amount of time it takes to run all of your tests by distributing the tests across multiple targets.

By default, QMTest uses only one target: the machine on which you are running QMTest. You may specify other targets by creating a target file, which lists the available targets and their attributes, and specifying the target file when you invoke qmtest.

Each target is a member of a single target group. All targets in the same target group are considered equivalent. A target group is specified by a string. If you are testing software on multiple platforms at once, the target group might correspond to machines running the same operating system. For example, all Intel 80386 compatible machines running GNU/Linux might be in the “i386-pc-linux-gnu” target group.

QMTest by default executes all tests using a 'serial target', i.e. one after another. This behavior can be changed by specifying a different concurrency strategy, such as one that uses multiple threads, multiple processes, or even multiple physical machines.

> qmtest create-target -a name=local -a group=local -a threads=2 a thread_target.ThreadTarget
   

This creates a 'thread target' where two threads are used to run the tests in parallel.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts-expectation-database.html0000664000076400007640000000567511122066675027174 0ustar stefanstefan5.Expectation Database

5.Expectation Database

While typically tests are expected to pass, it sometimes is meaningful to indicate a different expectation. QMTest represents expectations by results. Here, the outcomes represent the expectated outcome, and the annotations may explain the expectation.

An expectation database stores expectations associated with a test database. It provides an interface to query expectations by test id.

In the simplest case all tests are expected to pass. In a slightly less simple case, an existing set of results, obtained from a previous test run, may be used as expectations for a subsequent test run.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts-resources.html0000664000076400007640000001462211122066675025111 0ustar stefanstefan7.Resources

7.Resources

Some tests take a lot of work to set up. For example, a database test that checks the result of SQL queries may require that the database first be populated with a substantial number of records. If there are many tests that all use the same set of records, it would be wasteful to set up the database for each test. It would be more efficient to set up the database once, run all of the tests, and then remove the databases upon completion.

You can use a resource to gain this efficiency. If a test depends on a resource, QMTest will ensure that the resource is available before the test runs. Once all tests that depend on the resource have been run QMTest will destroy the resource.

Just as every test is an instance of a test class, every resource is an instance of a resource class. The resource class explains how to set up the resource and how to clean up when it is no longer needed. The arguments to the resource class are what make two instances of the same resource class different from each other. For example, in the case of a resource that sets up a database, the records to place in the database might be given as arguments. Every resource has a name, using the same format that is used for tests.

Under some circumstances (such as running tests on multiple targets at once), QMTest may create more than one instance of the same resource. Therefore, you should never depend on there being only one instance of a resource. In addition, if you have asked QMTest to run tests concurrently, two tests may access the same resource at the same time. You can, however, be assured that there will be only one instance of a particular resource on a particular target at any one time.

Tests have limited access to the resources on which they depend. A resource may place additional information into the context (Section6, “Context”) that is visible to the test. However, the actual resource object itself is not available to tests. (The reason for this limitiation is that for a target consisting of multiple processes, the resource object may not be located in the same process as the test that depends upon it.)

Setting up or cleaning up a resource produces a result, just like those produced for tests. QMTest will display these results in its summary output and record them in the results file.

Building on the previous example of a CompilationTest, let us consider a situation where some test application should be run multiple times with different arguments. The test application, however, needs to be compiled first. In order to avoid recompiling the application for each test, you can create a resource that compiles the application once. Then, tests that depend on this resource can assume that the application has already been built. The following commands:

> qmtest create --id applet resource
    compilation_test.CompiledResource(executable="applet", source_files="['/path/to/applet.cc']")
> qmtest create --id run_applet_0 test
    compilation_test.ExecutableTest(args="['0']", resources="['applet']")
> qmtest create --id run_applet_1 test
    compilation_test.ExecutableTest(args="['1']", resources="['applet']")
    

create a resource (named "applet") for the application and two tests ("run_applet_0" and "run_applet_1"), both of which make use of "applet", but which pass it different command-line options.

> qmtest run -c CompilationTest.compiler_path=g++ run_applet_0 run_applet_1
--- TEST RESULTS -------------------------------------------------------------

  Setup applet                                  : PASS

  run_applet_0                                  : PASS

  run_applet_1                                  : PASS

  Cleanup applet                                : PASS
    
qmtest-2.4.1/share/doc/qmtest/html/tutorial/extending-database-classes.html0000664000076400007640000001061511122066700026430 0ustar stefanstefan5.Writing Database Classes

5.Writing Database Classes

The test database class controls the format in which tests are stored. QMTest's default database class stores each test as an XML file, but you might want to use a format that is particularly well suited to your application domain or to your organization's arrangement of computing resources.

For example, if you were testing a compiler, you might want to represent tests as source files with special embedded comments indicating what errors are expected when compiling the test. You could write a test database class that can read and write tests in that format.

Or, if you wanted to share a single test database with many people in such a way that everyone automatically saw updates to the database, you might want to put all of the tests on a central HTTP server. You could write a test database class that retrieves tests from the server and creates new tests by uploading them to the server.

A test database class is a Python class that is derived from Database, which is itself derived from Extension. To create a new database class, you must define methods that read and write Extension instances.

The database is also responsible for determining how tests (and other entities stored in the database) are named. Each item stored in the database must have a unique name. For a database that stores files in the filesystem, the name of the file may be a good name. For a database of unit tests for Python module, the name of the module might be a good name for the tests. Choosing the naming convention appropriate requires understanding both the application domain and the way in which the tests will actually be stored.

The database class must have a GetExtension method which retrieves an instance of Extension given the name of the instance. If your database is modifiable, you must also provide WriteExtension and RemoveExtension methods. For historical reasons, your database class must also set the class variable _is_generic_database to true.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-gui.html0000664000076400007640000001735111122066676023466 0ustar stefanstefan5.qmtest gui

5.qmtest gui

5.1.Summary

Start the graphical user interface.

5.2.Synopsis

qmtest gui [ option ...]

5.3.Description

The qmtest gui starts the graphical user interface. The graphical user interface is accessed through a web browser. You must have a web browser that supports JavaScript to use the graphical interface. QMTest has been tested with recent versions of Internet Explorer and Netscape Navigator. Other web browsers may or may nor work with QMTest.

The gui command accepts these options:

-A address, --address address

Bind the server to the indicated internet address, which should be a dotted quad. By default, the server binds itself to the address 127.0.0.1, which is the address of the local machine. If you specify another address, the server will be accessible to users on other machines. QMTest does not perform any authentication of remote users, so you should not use this option unless you have a firewall in place that blocks all untrusted users.

-c name=value, --context name=value

For details about this option, see the description of the qmtest run command.

-C file, --load-context file

For details about this option, see the description of the qmtest run command.

--daemon

Run the QMTest GUI as a daemon. In this mode, QMTest will detach from the controlling terminal and run in the background until explicitly shutdown.

-j count, --concurrency count

For details about this option, see the description of the qmtest run command.

--no-browser

Do not attempt to start a web browser when starting the GUI. QMTest will still print out the URL at which the server can be accessed. You can then connect to this URL manually using the browser of your choice.

-O file, --outcomes file

For details about this option, see the description of the qmtest run command.

--pid-file path

Specify the path to which the QMTest GUI will write its process ID. This option is useful if you want to run QMTest as a daemon. If this option is not provided, no PID file is written. If you specify this option, but path is the empty string, QMTest will check the .qmrc configuration file for a pid-file entry. If there is no such entry, QMTest will use an appropriate platform-specific default value.

--port port

Specify the port on which the QMTest GUI will listen for connections. If this option is not provided, QMTest will select an available port automatically.

-T file, --targets file

For details about this option, see the description of the qmtest run command.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing.html0000664000076400007640000001523611122066700023625 0ustar stefanstefanChapter3.Customizing QMTest

Chapter3.Customizing QMTest

The previous chapter introduced the concepts underlying QMTest's design. These were demonstrated with particular types of tests, resources, databases, etc. . These types are designed to be extensible, i.e. QMTest can operate with arbitrary instances of these types. In fact, QMTest provides a large number of such extensions.

This chapter discusses how to use them, i.e. how to find out what extensions are available, and how to use them to construct custom test databases.

1.Extensions

In the previous chapter we have created a test database containing a number of tests. These tests were instances of test types, such as python.ExecTest. When creating a test, a user chooses a test type, and assigns test-specific parameters to it.

The same extension mechanism is used for other aspects of QMTest's functionality. All these types are extensions, which provide a generic interface for QMTest to query.

To find out what extensions are available, use qmtest extensions. To list all available test types, use:

> qmtest extensions -k test
** Available test classes **

- command.ExecTest

  Check a program's output and exit code.

- command.ShellCommandTest

  Check a shell command's output and exit code.

- python.ExecTest

  Check that a Python expression evaluates to true.

...
   

To find out more about a particular extension type, use the describe command:

> qmtest describe test command.ExecTest

class name: python.ExecTest
   Check that a Python expression evaluates to true.

class attributes:
   prerequisites     The tests on which this test depends.
   source            The source code.
   target_group      The targets on which this test can run.
   expression        The expression to evaluate.
   resources         Resources on which this test or resource depends.
   

To create a test of that type, you can call:

> qmtest create --id=my_test -a expression='True' test python.ExecTest
   

where the extension parameters are specified with the -a option.

QMTest searches for extensions in particular places, in the following order:

  1. in the paths contained in the QMTEST_CLASS_PATH environment variable.

  2. in the class-path associated with a particular test database (typically the QMTest/ subdirectory).

  3. in the site-extension path associated with a particular QMTest installation.

  4. in the set of built-in extensions that come with a particular QMTest installation.

This search allows users to provide their own extension types. See Chapter4, Extending QMTest for a detailed discussion of how to create new extensions.

The rest of this chapter will discuss the various extension kinds that can be used to customize QMTest.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-create.html0000664000076400007640000001770011122066675024142 0ustar stefanstefan2.qmtest create

2.qmtest create

2.1.Summary

Create a new extension instance.

2.2.Synopsis

qmtest create [ option ...] kind descriptor

2.3.Description

The qmtest create creates a new extension instance. For example, this command can be used to create a new test or resource. For a list of the kinds of extensions supported by QMTest, run qmtest extensions. The kind must be one of these extension kinds.

If the --id option is provided then the new instance is created in the test database. The argument to the --id option gives the name of the instance. Otherwise, the extension is written as XML to the filename specified by --output option, or to the standard output if no --output is specified.

The descriptor specifies an extension class and (optionally) attributes for that extension class. The form of the descriptor is class(attributes), where the attributes are of the form attr = "val". If there are no attributes, the parentheses may be omitted.

The class may be either the path to an extensing extension or a QMTest class name in the form module.class. If the --id option has been provided, QMTest will look for an existing extension in the test database named class. If the --id option has not been provided, QMTest will look for an XML file named class. In either case, if an existing extension cannot be found, the class is interepreted as the name of an extension class.

The attributes used to construct the extension instance come from three sources: the attributes in the extant extension (if the class is the path to an extension file), the --attribute options provided on the command line, and the explicit attributes provided in the descriptor. If multiple values for the the same attribute name are provided, the value used is taken from the first source in the following list for which there is a value: the rightmost attribute provided in the descriptor, the extension file, or the rightmost --attribute present on the command line.

The create command accepts these options:

-a name=value, --attribute name=value

Set the target class argument name to value. The set of valid argument names and valid values is dependent on the extension class in use.

-i id, --id id

Add the extension instance to the database, using id as the name of the instance.

-o file, --output file

Write the extension instance to file.

2.4.Example

This command:


 qmtest create -a format=stats -o rs
        result_stream text_result_stream.TextResultStream(filename="rs")

creates a file called rs containing an instance of TextResultStream.

This command:

> qmtest create --id=simple -a program=testprog test command.ExecTest
    

creates a test named "simple" that executes the program testprog:

This command:

> qmtest create --id=copy test simple
    

creates a copy of the "simple" test, naming the new version "copy".

qmtest-2.4.1/share/doc/qmtest/html/tutorial/index.html0000664000076400007640000002324711122066700022362 0ustar stefanstefanQMTest: User's Guide

QMTest: User's Guide

CodeSourcery, Inc.

Version 2.4.1

Abstract

QMTest is a testing tool. You can use QMTest to test a software application, such as a database, compiler, or web browser. You can even QMTest to test a physical system (like a valve or thermometer) if you have a way of connecting it to your computer.

Code that has not been tested adequately generally does not work. Yet, many applications are deployed without adequate testing, often with catastrophic results. It is much more costly to find defects at the end of the release cycle than at the beginning. By making it easy to develop tests, and execute those tests to validate the application, QMTest makes it easy to find problems easier, rather than later.

QMTest can be extended to handle any application domain and any test format. QMTest works with existing testsuites, no matter how they work or how they are stored. QMTest's open and pluggable architecture supports a wide variety of applications.

QMTest features both an intuitive graphical user interface and a conventional command-line interface. QMTest can run tests in serial, in parallel on a single machine, or across a farm of possibly heterogeneous machines.

CodeSourcery provides support for QMTest. CodeSourcery can help you install, integrate, and customize QMTest. For more information, visit the QMTest web site.


qmtest-2.4.1/share/doc/qmtest/html/tutorial/extending-field-classes.html0000664000076400007640000002266411122066700025756 0ustar stefanstefan2.Field Classes

2.Field Classes

Field instances are used to represent extension parameters. A Field can read and write XML representations of values, generate HTML representations of values, or present HTML forms that permit the user to update the value of the field. There are several classes derived from Field that you can use in extension classes. If none of those classes satisfy your needs, you can create a new class derived from Field.

A Field may have a title, which is used when presenting the Field to the user. The title need not be a valid Python identifier. For example, the RSHTarget class has a host parameter whose title is Remote Host Name. When accessing an instance of this class, the programmer refers to self.host. In the GUI, however, the user will see the value presented as Remote Host Name.

A Field may have an associated description, which is a longer explanation of the Field and its purpose. This information is presented to the user by the GUI.

A Field may have a default value. The default value is used if no argument is provided for the field when the extension is initialized.

This example code from RSHTarget shows how a Field is constructed:

 remote_shell = qm.fields.TextField(
        title="Remote Shell Program",
        description="""The path to the remote shell program.

         The name of the program that can be used to create a
         remote shell.  This program must accept the same command
         line arguments as the 'rsh' program.""",
         default_value="ssh")

  

See the internal documentation for Field for complete interface documentation.

2.1.Built-In Field Classes

QMTest comes with several useful field classes:

2.2.Writing Field Classes

Before writing any code, you should decide what kind of data your field class will store. For example, will your field class store arbitrary strings? Or only strings that match a particular regular expression? Or will your field class store images? Once you have decided this question, you can write the Validate function for your field class. This function checks an input value (a Python object) for validity. Validate can return a modified version of the value. For example, if the field stores strings, you could choose to accept an integer as an input to Validate and convert the integer to a string before returning it.

The FormatValueAsHtml function produces an HTML representation of the value. You must define this function so that the GUI can display the value of the field. The style parameter indicates how the value should be displayed. If the style is new or edit, the HTML representation returned should be a form that the user can use to set the value. If the user does not modify the form, ParseFormValue should yield the value that was provided to FormatValueAsHtml.

The MakeDomNodeForValue and GetValueFromDomNode functions convert values to and from XML format. The FormatValueAsText and ParseTextValue functions convert to and from plain text. As with FormatValueAsHtml and ParseFormValue, these pairs of functions should be inverses of one another.

The ParseTextValue, ParseFormValue, and GetValueFromDomNode functions should use Validate to check that the values produced are permitted by the Field. In this way, derived classes that want to restrict the set of valid values, but are otherwise content to use the base class functionality, need only provide a new implementation of Validate.

All of the functions which read and write Field values may raise exceptions if they cannot complete their tasks. The caller of the Field is responsible for handling the exception if it occurs.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts-hosts.html0000664000076400007640000000565511122066675024245 0ustar stefanstefan9.Hosts

9.Hosts

Sometime it is necessary to execute a test application on a different machine than the one running the qmtest application itself. For example, if the test involves executing an application previously cross-compiled, the binary needs to be uploaded to an appropriate host and run there.

QMTest provides a host abstraction for this purpose. To use this mechanism, test classes need to provide explicit support for it. A number of built-in test classes support cross-testing.

To run the compile test on a remote target machine, specify a CompilationTest.target variable in the context file to contain a host descriptor:

CompilationTest.compiler=/path/to/cross_compiler
CompilationTest.target=ssh_host.SSHHost(host_name="192.168.0.100")
   

This will run the compiled executable on the machine with the IP address 192.168.0.100, using ssh for communication.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-suites.html0000664000076400007640000000352711122066677025154 0ustar stefanstefan3.Test Suites

3.Test Suites

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-resources.html0000664000076400007640000000736311122066677025654 0ustar stefanstefan4.Test Resources

4.Test Resources

4.1.TempDirectoryResource

An instance of this resource creates a temporary directory during setup, and deletes it during cleanup. The full path to the directory is available to tests via a context property.

dir_path_property (text field)

The name of the context property which is set to the path to the temporary directory.

4.2.CompilerTable

A CompilerTable resource creates a set of compiler objects according to context variables. These compiler objects are then made available to test instances through the compilers context variable that maps language names to compiler objects.

The context variable CompilerTable.languages should be a whitespace-separated list of programming language names. Then, for each language <lang>, the following variables are looked up and used for the creation of compiler objects:

CompilerTable.<lang>_kind (text field)

The kind of compiler (e.g., "GCC" or "EDG").

CompilerTable.<lang>_path (text field)

The path to the compiler.

CompilerTable.<lang>_options (text field)

A whitespace-separated list of command-line options to provide to the compiler.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/cs.css0000664000076400007640000000226611107032207021500 0ustar stefanstefan/********* Headings *********/ h1, h2, h3 { font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; margin-top: 2px; padding-top: 2px; } h1 { font-size: 14px; color: #111111; margin-bottom: 0px; padding-bottom: 0px; text-transform: capitalize; } h2 { font-size: 11px; color: #222222; margin-bottom: 2px; padding-bottom: 2px; text-transform: capitalize; } h3 { font-size: 10px; color: #333333; font-style: italic; margin-top: 3px; margin-bottom: 3px; padding-top: 3px; padding-bottom: 3px; } /*@import url("http://www.codesourcery.com/codesourcerystyles.css");*/ body { /* The CodeSourcery stylesheet sets the margin for the body to 0px, but here we do not have the same graphical elements. */ margin: 8px; } pre.programlisting, pre.screen { font-size: smaller; border: 1px solid #aaaaaa; background-color: #eeeeee; margin: 20px; padding: 10px; } /* This is the same style used for ".code" in the CodeSourcery stylesheet. */ .guibutton,.guimenu,.guisubmenu,.guimenuitem { font-family: "Courier New", Courier, mono; font-size: 11px; line-height: 15px; color: #000000; } .remark { color: #ff0000; } qmtest-2.4.1/share/doc/qmtest/html/tutorial/extending.html0000664000076400007640000001761611122066700023243 0ustar stefanstefanChapter4.Extending QMTest

Chapter4.Extending QMTest

If the built-in functionality provided with QMTest does not serve all of your needs, you can extend QMTest. All extensions to QMTest take the form of Python classes. You can write new test classes, resource classes, or database classes in this way.

The contents of the class differ depending on the kind of extension you are creating. For example, the methods that a new test class must implement are different from those that must be provided by a new database class. In each case, however, you must create the class and place it in a location where QMTest can find it. The following sections explain how to create extension classes. The last section in this chapter explains how to register your new extension classes.

1.Extension Classes

All extensions to QMTest are implemented by writing a new Python class. This new Python class will be derived from an appropriate existing QMTest Python class. For example, new test classes are derived from Test while new test database classes are derived from Database.

The classes from which new extensions are derived (like Test) are all themselves derived from Extension. The Extension class provides the basic framework used by all extension classes. In particular, every instance of Extension can be represented in XML format in persistent storage.

Every Extension class has an associated list of parameter attributes. When an Extension instance is written out as XML, the value of each parameter is encoded in the output. Similarly, when an Extension instance is read back in, the parameter values are decoded. Conceptually, two Extension instances are the same if they are instances of the same derived class and their parameters have the same values.

Each parameter has a type. For example, every Test has a parameter called target_group. The target group is a string indicating on which targets a particular test should be run.

Each parameter is represented by an instance of Field. A Field instance can read or write values in XML format. A Field can also produce an HTML representation of a value, or an HTML form that allows a user to update the value of the field. It is the fact that all Extension parameters are instances of Field that makes it possible to represent Extension instances as XML. Smilarly, it is the use of the Field class that allows the user to edit tests in the QMTest GUI.

Each class derived from Extension may contain attributes that are instances of Field.

For example, after the following class definitions:

    class A(Extension):
        x = TextField()

    class B(A):
        y = IntegerField(default_value = 42)
        z = TextField(default_value = "a value")
  

A has one parameter (x) and B has three parameters (x, y, and z).

During construction of extensions you may provide arguments to set the values of these parameters (and thus overriding default values):

    a = A(x = "argument")
    b = B(x = "another argument", z = "value")
  

The serialized form of A will be equivalent to

<extension class="__main__.A">
  <argument name="x"><text>argument</text></argument>
</extension>
  

and for B

<extension class="__main__.B">
  <argument name="x"><text>another argument</text></argument>
  <argument name="y"><integer>42</integer></argument>
  <argument name="z"><text>value</text></argument>
</extension>
  

Extension instances hold appropriately typed attributes for all fields. A TextField translates to a str instance, while a IntegerField translates to an int, etc.

> a = A(x = "argument")
> print type(a.x), a.x
<type 'str'> argument
  
qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts-context.html0000664000076400007640000001142111122066675024555 0ustar stefanstefan6.Context

6.Context

When you create a test, you choose arguments for the test. The test class uses this information to run the test. However, the test class may sometimes need information that is not available when the test is created. For example, if you are writing compiler tests to verify conformance with the C programming language specification, you do not know the location of the C compiler itself. The C compiler may be installed in different locations on different machines.

A context gives users a way of conveying this kind of information to tests. The context is a set of key/value pairs. The keys are always strings. The values of all context properties provided by the user are strings. In general, all tests in a given use of QMTest will have the same context. However, when a resource is set up, it may place additional information in the context of those tests that depend upon it. The values inserted by the resource may have any type, so long as they can be "pickled" by Python.

All context properties whose names begin with "qmtest." are reserved for use by QMTest. The values inserted by QMTest may have any type. Test and resource classes should not depend on the presence or absence of these properites.

To understand how a context is used during the execution of a test let us start by creating a somewhat less trivial test:

> qmtest create --id compile test 
    compilation_test.CompilationTest(executable="compile", source_files="['/path/to/compile.cc']")"
    

When run, this test will compile /path/to/compile.cc and run the resulting executable. The test passes if compilation succeeds, and the program exit status indicates success.

The compilation_test.CompilationTest test class requires that the compiler be available in the context with the key CompilationTest.compiler_path. You can provide a context variable to QMTest either through a context file or on the command-line using the -c option. For example:

> qmtest run -c CompilationTest.compiler_path=g++ compile
    

will run the test using the g++ compiler, while:

> qmtest run -c CompilationTest.compiler_path=/bin/CC compile
    

will run the test with the /bin/CC compiler.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts.html0000664000076400007640000004065011122066675023101 0ustar stefanstefanChapter1.QMTest Concepts

Chapter1.QMTest Concepts

This section presents the concepts that underlie QMTest's design. By understanding these concepts, you will be able to better understand how QMTest works. In addition, you will find it easier to extend QMTest to new application domains.

The central principle underlying the design of QMTest is that the problem of testing can be divided into a domain-dependent problem and a domain-independent problem. The domain-dependent problem is deciding what to test and how to test it. For example, should a database be tested by performing unit tests on the C code that makes up the database, or by performing integration tests using SQL queries? How should the output of a query asking for a set of records be compared to expected output? Does the order in which records are presented matter? These are questions that only someone who understands the application domain can answer.

The domain-independent part of the problem is managing the creation of tests, executing the tests, and displaying the results for users. For example, how does a user create a new test? How are tests stored? Should failing tests be reported to the user, even if the failure was expected? These questions are independent of the application domain; they are just as relevant for compiler tests as they are for database tests.

QMTest is intended to solve the domain-independent part of the problem and to offer a convenient, powerful, and flexible interface for solving the domain-dependent problem. QMTest is both a complete application, in that it can be used “out of the box” to handle many testing domains, and infrastructure, in that it can be extended to handle other domains.

Throughout this chapter we will use the qmtest application with a variety of parameters and options. For a full description of the qmtest please refer to the command-line reference.

The following commands create a simple test database in the current working directory. This test database will be used throughout the following sections of this tutorial.

> mkdir tdb
> cd tdb
> qmtest create-tdb
  

1.Tests

A test checks for the correct behavior of the target application. What constitutes correct behavior will vary depending on the application domain. For example, correct behavior for a database might mean that it is able to retrieve records correctly while correct behavior for a compiler might mean that it generates correct object code from input source code.

Every test has a name that uniquely identifies the test, within a given test database. Test names must be composed entirely of lowercase letters, numbers, the “_” character, and the “.” character. You can think of test names like file names. The “.” character takes the place of “/”; it allows you to place a test in a particular directory. For example, the test name a.b.c names a test named c in the directory a.b. The directory a.b is a subdirectory of the directory a.

Every test is an instance of some test class. The test class dictates how the test is run, what constitutes success, and what constitutes failure. For example, the command.ExecTest class that comes with QMTest executes the target application and looks at its output. The test passes if the actual output exactly matches the expected output.

The arguments to the test parameterize the test; they are what make two instances of the same test class different from each other. For example, the arguments to command.ExecTest indicate which application to run, what command-line arguments to provide, and what output is expected.

The python.ExecTest class is similar to command.ExecTest, but, instead of executing a command using the system shell, it evaluates an expression in the Python programming language. The test passes if (and only if) the expression is true. In Python, the expressions True and False are literals.

The following creates two trivial tests, python_pass and python_fail:

> qmtest create --id=python_pass -a expression='True' test python.ExecTest
> qmtest create --id=python_fail -a expression='False' test python.ExecTest
    

The first test will always pass while the second will always fail.

The qmtest ls command will show the content of the test database:

> qmtest ls
python_fail
python_pass
    

Similar to the Unix ls command, the -l option can be used to provide a detailed listing, with kind ("test", "resource", or "suite"), extension class, and id:

> qmtest ls -l
test python.ExecTest python_fail
test python.ExecTest python_pass
    

1.1.Running Tests

To run one or more tests, use the qmtest run command:

> qmtest run
      

Each invocation of the qmtest run command is a single test run, and produces a single set of test results and statistics. Specify as arguments the names of tests and test suites to run. Even if you specify a test more than once, either directly or by incorporation in a test suite, QMTest runs it only once.

If you wish to run all tests in the test database, use the implicit test suite . (a single period; see Section3.1, “Implicit Test Suites”), or omit all IDs from the command line.

QMTest can run tests in multiple concurrent threads of execution or on multiple remote hosts. See the documentation for the run command for details.

How the output of the qmtest run command should be interpreted will be discussed in Section2, “Test Results”.

1.2.Prerequisite Tests

QMTest can avoid running one test (a "dependent test") when some other test (a "prerequisite test") has a particular outcome.

Suppose that you have a test database with a very simple test that can be run very quickly, and a very complex test that takes hours to run. You know that if the simple test fails, then there is no chance that the complex test will pass. In that case, you could make the simple test a prerequisite of the complex test. Then, when you run both tests, QMTest will run the simple test first. If it fails, the complex test will not be run at all.

Alternatively, suppose that you have a very comprehensive test that tests ten features of your software. You also have ten separate tests, one for each feature. The comprehensive test can be run in one minute; runnning the separate tests takes two minutes each. So, you want to run the comprehensive test first; if it passes, there is no need to run the individual tests. However, if the comprehensive test fails, you may want to run the single tests to isolate the problem. In this case, each of the simple tests would have the comprehensive test as a prerequisite, indicating that the simple test should be run only if the comprehensive test fails.

If you explicitly run just the dependent test, QMTest will not run the prerequisite test automatically. In other words, prerequisites are an optimization; when running both the prerequisite and the dependent test, QMTest will run them in the order you've implied, and can omit the dependent test if it is not useful. But, QMTest will not automatically force you to run the prerequisite tests when you only want to run the dependent test.

Because prerequisite tests are not run unless you ask for them, the dependent test should not depend in any way on the prerequisite test. Otherwise, users will see different test outcomes when they run the dependent test by itself. In other words, each test should stand alone; the order in which tests are run should not affect their outcomes.

1.3.Ordering and Dependencies

Given one or more input test names and test suite names, QMTest employs the following procedure to determine which tests and resources to run and the order in which they are run.

  1. QMTest resolves test names and test suite names. Test suites are expanded into the tests they contain. Since test suites may contain other test suites, this process is repeated until all test suites have been expanded. The result is a set of tests that are to be run.

  2. QMTest computes a schedule for running the tests to be run such that a test's prerequisites are run before the test itself is run. Prerequisites not included in the test run are ignored. Outside of this condition, the order in which tests are run is undefined.

    If QMTest is invoked to run tests in parallel or distributed across several targets, the tests are distributed among them as well. QMTest does not guarantee that a test's prerequisites are run on the same target, though. On each target, tests are assigned to the next available concurrent process or thread.

  3. QMTest determines the required resources for the tests to be run. If several tests require the same resource, QMTest attempts to run all of the tests on the same target. In this case, the resource is set up and cleaned up only once. In some cases, QMTest may schedule the tests on multiple targets; in that case, the resource is set up and cleaned up once on each target.

In the following cases, a test or resource will not be executed, even though it is included in the set of tests enumerated above:

  • A test specifies for each of its prerequisite tests an expected outcome. If the prerequisite is included in the test run and the actual outcome of the prerequisite test is different from the expected outcome, the test is not run. Instead, it is given an UNTESTED outcome.

    If a test's prerequisite is not included in the test run, that prerequisite is ignored.

  • If a setup function for one of the resources required by a test fails, the test is given an UNTESTED outcome.

  • The cleanup function of a resource is run after the last test that requires that resource, whether or not that test was run. The cleanup function is run even if the setup function failed.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-summarize.html0000664000076400007640000001332211122066676024710 0ustar stefanstefan11.qmtest summarize

11.qmtest summarize

11.1.Summary

The qmtest summarize displays information stored in a results file.

11.2.Synopsis

qmtest summarize [ option ...] [{results-file} [ test-name | suite-name ...]]

11.3.Description

The qmtest summarize extracts information stored in the results-file (or results.qmr, if no results-file is specified) and displays this information on the console. The information is formatted just as if the tests had been run with qmtest run, but, instead of actually running the tests, QMTest reads the results from the results-file.

If the results-file is not a valid results file, it is interpreted as an extension descriptor, as described in Section2, “qmtest create. You can use the descriptor syntax to read results stored in formats that are not "built-in" to QMTest.

The summarize command accepts the following options:

-f format, --format format

For details about this option, see the description of the qmtest run command.

-o file, --output file

Write full test results to file, in QMTest's machine-readable file format. Use a "-" (a hyphen) to write results to the standard output.

-O file, --outcomes file

For details about this option, see the description of the qmtest run command.

--result-stream descriptor

Specify an additional output result stream. The descriptor is in the format described in Section2, “qmtest create.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/concepts-test-suite.html0000664000076400007640000001541011122066675025201 0ustar stefanstefan3.Test Suites

3.Test Suites

A test suite is a collection of tests. QMTest can run an entire test suite at once, so by grouping tests together in a test suite, you make it easier to run a number of tests at once. A single test can be a member of more than one test suite. A test suite can contain other test suites; the total set of tests in a test suite includes both those tests included directly and those tests included as part of another test suite. Every test suite has a name, following the same conventions given above for tests.

One use of test suites is to provide groups of tests that are run in different situations. For example, the nightly test suite might consist of those tests that should be run automatically every night, while the checkin test suite might consist of those tests that have to pass before any changes are made to the target application.

3.1.Implicit Test Suites

Section1, “Tests” explains how you may arrange tests in a tree hierarchy, using a period (“.”) as the path separator in test names. QMTest defines an implicit test suite for each directory. The name of these implicit test suites is the same as the name of the directory. The implicit test suite corresponding to a directory contains all tests in that directory or its subdirectories.

Let us create some more tests, but this time within their respective subdirectories:

> qmtest create --id=dir1.one -a expression='True' test python.ExecTest
> qmtest create --id=dir1.two -a expression='False' test python.ExecTest
> qmtest create --id=dir2.one -a expression='True' test python.ExecTest
> qmtest create --id=dir2.dir3.one -a expression='False' test python.ExecTest
> qmtest create --id=dir2.dir3.two -a expression='False' test python.ExecTest
      

This will create five new tests, together with three directories:

> qmtest ls -lR
directory                 dir1
test      python.ExecTest dir1.one
test      python.ExecTest dir1.two
directory                 dir2
directory                 dir2.dir3
test      python.ExecTest dir2.dir3.one
test      python.ExecTest dir2.dir3.two
test      python.ExecTest dir2.one
      

These directories are implicit suites, i.e. it is possible to only address tests within them:

> qmtest ls -lR dir2
directory                 dir2
directory                 dir2.dir3
test      python.ExecTest dir2.dir3.one
test      python.ExecTest dir2.dir3.two
test      python.ExecTest dir2.one
      

The suite named "." (a single period) is the implicit test suite corresponding to the root directory in the test database. This suite therefore contains all tests in the database. For example, the command

> qmtest run .
    

is equivalent to:

> qmtest run
    

Both commands run all tests in the database.

3.2.Explicit Test Suites

Explicit test suites are a means to refer to a set of tests for the purpose of executing them together, no matter how they are organized in the test database. For example, you may want to run a subset of all tests nightly. To do this, you create a suite, listing all tests (as well as contained suites) explicitely:

> qmtest create --id=nightly suite explicit_suite.ExplicitSuite(test_ids="['dir1.one', 'dir2.one']",
                                                                suite_ids="['dir2.dir3']")
> qmtest ls -l
directory                              dir1
directory                              dir2
suite     explicit_suite.ExplicitSuite nightly
> qmtest ls -l nightly
test      python.ExecTest dir1.one
directory                 dir2.dir3
test      python.ExecTest dir2.one
      
qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-tests.html0000664000076400007640000002523211122066677024777 0ustar stefanstefan2.Tests

2.Tests

2.1.command.ExecTest

The command.ExecTest test class runs a program from an ordinary executable file. Each test specifies the program executable to run, its full command line, and the data to feed to its standard input stream. ExecTest collects the complete text of the program's standard output and standard error streams and the program's exit code, and compares these to expected values specified in the test. If the standard output and error text and the exit code match the expected values, the test passes.

A command.ExecTest test supplies the following arguments:

Program (text field)

The name of the executable file to run. command.ExecTest attempts to locate the program executable in the path specified by the path property of the test context.

Argument List (set of strings)

The argument list for the program. The elements of this set are sequential items from which the program's argument list is constructed. command.ExecTest automatically prepends an implicit zeroth element, the full path of the program.

Standard Input (text field)

Text or data to pass to the program's standard input stream. This data is written to a temporary file, and the contents of the file are directed to the program's standard input stream.

Environment (set of strings)

The environment (i.e. the set of environment variables) available to the executing program. Each element of this argument is a string of the form "VARIABLE=VALUE".

command.ExecTest adds additional environment variables automatically.

In addition, every context property whose value is a string is accessible as an environment variable; the name of the environment variable is the name of the context property, prefixed with "QMV_" and with any dots (".") replaced by a double underscore ("__"). For example, the value of the context property "CompilerTable.c_path" is available as the value of the environment variable "QMV_CompilerTable__c_path".

Expected Exit Code (integer field)

The exit code value expected from the program. If the program produces an exit code value different from this one, the test fails.

Expected Standard Output (text field)

The text or data which the program is expected to produce on its standard output stream. The actual text or data written to standard output is captured, and command.ExecTest performs a bytewise comparison to the expected text or data. If they do not match, the test fails.

Expected Standard Error (text field)

The text or data which the program is expected to produce on its standard error stream. The actual text or data written to standard error is captured, and command.ExecTest performs a bytewise comparison to the expected text or data. If they do not match, the test fails.

2.2.command.ShellCommandTest

command.ShellCommandTest is very similar to command.ExecTest, except that it runs a program via the shell rather than directly. Instead of specifying an executable to run and the elements of its argument list, a test provides a single command line. The shell is responsible for finding the executable and constructing its argument list.

Standard input and the environment are specified in the test. The test passes if the command produces the expected standard output, standard error, and exit code.

Note that most shells create local shell variables to mirror the contents of the environment when the shell starts up. Therefore, the environment set up by a command.ShellCommandTest, including the contents of the test context, are directly accessible via shell variables. The syntax to use depends on the particular shell.

command.ShellCommandTest has the same fields as command.ExecTest, except that the Program and Argument List properties are replaced with these:

Command (text field)

The command to run. The command is delivered verbatim to the shell. The shell interprets the command according to its own quoting rules and syntax.

2.3.command.ShellScriptTest

command.ShellScriptTest is an extension of command.CommandTest that lets a test specify an entire shell script instead of a single command. The script specified in the test is written to a temporary file, and this file is interpreted by the specified shell or command interpreter program.

Standard input, the environment, and the argument list to pass to the script are specified in the test. The test passes if the script produces the expected standard output, standard error, and exit code.

Note that most shells create local shell variables to mirror the contents of the environment when the shell starts up. Therefore, the environment set up by a command.ShellScriptTest, including the contents of the test context, are directly accessible via shell variables. The syntax to use depends on the particular shell.

command.ShellScriptTest has the same fields as command.ExecTest, except that the Program property is replaced with:

Script (text field)

The text of the script to run.

2.4.CompilationTest

compilation_test.CompilationTest compiles a set of source files and optionally runs the compiled executable.

The compiler executable's name, as well as global compilation parameters are queried from these context variables:

CompilationTest.compiler_path

The name of the compiler executable.

CompilationTest.compiler_options

Compiler options.

CompilationTest.compiler_ldflags

Linker options.

The CompilationTest takes the following parameters.

options (set field)

Test-specific options to pass to the compiler.

ldflags (set field)

Test-specific linker flags to pass to the compiler.

source_files (set field)

Source files to be compiled..

executable (text field)

The name of the executable to be compiled.

execute (boolean field)

Whether or not to run the compiled executable.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-ls.html0000664000076400007640000001005511122066676023312 0ustar stefanstefan8.qmtest ls

8.qmtest ls

8.1.Summary

List the contents of the test database.

8.2.Synopsis

qmtest ls [ option ...] [ name ...]

8.3.Description

The qmtest ls lists the contents of the database, just as the UNIX ls command lists the contents of the filesystem. If this command is used with no options, QMTest will list the names of the entries in the root directory of the test database. If one or more names are supplied, then QMTest will list those items, rather than the root directory. If a name refers to a directory, then the contents of that directory will be displayed.

The ls command accepts these options:

-l , --long

Use a detailed output format that displays the kind and extension class associated with each item.

-d , --details

Display details such as individual attributes for each item.

-R , --recursive

Recursively list the contents of directories.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-expectation-databases.html0000664000076400007640000001303311122066677030101 0ustar stefanstefan6.Expectation Databases

6.Expectation Databases

6.1.PreviousTestRun

The PreviousTestRun queries expectations from a results file. Thus, running QMTest twice, the second time using the results of the first test run as expectations, will result in no unexpected results:

> qmtest run -o my_results.qmr
--- TEST RESULTS -------------------------------------------------------------

  exec0                                         : PASS

  exec1                                         : FAIL
    ...
  exec2                                         : PASS

--- TESTS THAT DID NOT PASS --------------------------------------------------

  exec1                                         : FAIL
    Expression evaluates to false.


--- STATISTICS ---------------------------------------------------------------

       3        tests total
       1 ( 33%) tests FAIL
       2 ( 67%) tests PASS

> qmtest run -e previous_testrun.PreviousTestRun(file_name="my_results.qmr")
--- TEST RESULTS -------------------------------------------------------------

  exec0                                         : PASS

  exec1                                         : XFAIL
    ...
  exec2                                         : PASS

--- TESTS WITH UNEXPECTED OUTCOMES -------------------------------------------

  None.


--- STATISTICS ---------------------------------------------------------------

       3 (100%) tests as expected

     

Since taking previous test runs as expectations is a common use case, the second command above may be expressed in a more compact form as:

qmtest run -O my_results.qmr

The PreviousTestRun takes the following parameters.

file_name (text field)

The filename of the results file.

6.2.XMLExpectationDatabase

The XMLExpectationDatabase stores expectations in an XML file. Instead of containing expectations for all tests, individual expectations are computed from rules by matching test-ids as well as test-run annotations against specific rules.

<expectations>
  <expectation outcome="fail" test_id=".*">
    <annotation name="a" value="b"/>
  </expectation>
  <expectation outcome="fail" test_id="first*" />
</expectations>
     

The above little expectation database thus contains the following rules (subsequent matching rules override previous matching rules):

  1. All tests are expected to fail if the annotation a has value b.

  2. All tests whose test-ids start with first are expected to fail.

The XMLExpectationDatabase takes the following parameters.

file_name (text field)

The filename of the xml expectations file.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-config-file.html0000664000076400007640000001426311122066677026021 0ustar stefanstefan10.The QMTest Configuration File

10.The QMTest Configuration File

QMTest allows you to set up a per-user configuration file that contains your personal preferences, defaults, and settings.

The configuration file is named $HOME/.qmrc. On Windows, you may have to set the HOME environment variable manually.

The QMTest configuration file is a plain text file, with a format similar to that used in Microsoft Windows .INI files. It is divided into sections by headings in square brackets. Three sections are supported: [common] contains configuration variables common to all the QM tools, while [test] contains configuration variables specific to QMTest. Within each section, configuration variables are set using the syntax variable=value.

Here is a sample QM configuration file:

> cat ~/.qmrc
[common]
browser=/usr/local/bin/mozilla

10.1.Configuration Variables

These configuration variables are used in all QM tools. You should define them in the [common] section of your QM configuration file.

browser (UNIX-like platforms only)

The path to your preferred web browser. If omitted, QM attempts to run mozilla. The QM GUI does not correctly with Netscape 4 due to limitations in the support for JavaScript and DOM in that browser.

command_shell

The shell program to run a single shell command. The value of this property is the path to the shell executable, optionally followed by command-line options to pass to the shell, separated by spaces. The shell command to run is appended to the command.

On GNU/Linux systems, the default is /bin/bash -norc -noprofile -c. On other UNIX-like systems, the default is /bin/sh -c.

click_menus

If this option is not present, or has the value 0, menus in the GUI are activated by moving the mouse over the menu name.

If this option has the value 1, the menus are activated by clicking on the menu name.

remote_shell (UNIX-like platforms only)

The program used for running commands on remote computers. The program must accept the same syntax as the standard rsh command, and should be configured to run the command remotely without any additional interaction (such as requesting a password from the TTY). The default value is /usr/bin/ssh.

script_shell

The shell program to run a shell script. The value of this property is the path to the shell executable, optionally followed by command-line options to pass to the shell, separated by spaces. The filename of the shell command is appended to the command.

On GNU/Linux systems, the default is /bin/bash -norc -noprofile. On other UNIX-like systems, the default is /bin/sh.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-register.html0000664000076400007640000000735211122066676024526 0ustar stefanstefan9.qmtest register

9.qmtest register

9.1.Summary

Register an extension class.

9.2.Synopsis

qmtest register kind class-name

9.3.Description

The qmtest register registers an extension class with QMTest. As part of this process, QMTest will load your extension class. If the extension class cannot be loaded, QMTest will tell you what went wrong.

QMTest will search for your extension class in the directories it would search when running tests, including those given by the environment variable QMTEST_CLASS_PATH.

The kind argument tells QMTest what kind of extension class you are registering. If you invoke qmtest register with no arguments it will provide you with a list of the available extension kinds.

The class-name argument gives the name of the class in the form module.Class. QMTest will look for a file whose basename is the module name and whose extension is either py, pyc, or pyo.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/customizing-test-databases.html0000664000076400007640000001252511122066677026542 0ustar stefanstefan5.Test Databases

5.Test Databases

5.1.XMLDatabase

The XMLDatabase stores its content as a directory hierarchy containing XML files. It is the default test database used by QMTest. Each QMTest subdirectory is represented by a subdirectory in the filesystem. A test, suite, or resource is represented by an XML file. These files have file extensions .qmt, .qms, and .qma, respectively.

Expert QMTest users may modify the contents of the test database directly by editing these files. However, it is the user's responsibility to ensure the integrity and validity of the XML contents of each file. For example, file and directory names should contain only characters allowed in identifiers (lower-case letters, digits, hyphens, and underscores); a period should only be used before a file extension, such as .qmt. Also, the files and directories in a test database should not be modified directly while QMTest is running with that test database.

5.2.CompilationTestDatabase

The CompilationTestDatabase associates source files with CompilationTest instances. The mapping uses file extensions to determine the programming language, and thus, what compiler and compilation flags to use. To create a new test, simply add a source file with an appropriate file extension to the test database.

All tests use the CompilerTable resource, and therefor require the appropriate context variables to be provided.

Additionally, more compiler options can be added per test id or even subdirectory id. Given the following context file:

CompilerTable.languages=c
CompilerTable.c_kind=GCC
CompilerTable.c_path=gcc
CompilerTable.c_options=-O2
a.b.c_options=-I /a/b/common
a.b.c.c_options=-I /a/b/c
     

a test a/b/c/test.c will be compiled with gcc -O2 -I /a/b/common -I /a/b/c while a test a/b/d/test.c will be compiled with gcc -O2 -I /a/b/common.

The CompilationTestDatabase takes the following parameters.

srcdir (text field)

The root of the test suite's source tree.

excluded_subdirs (set field)

A set of directory names not to be parsed as subdirectories.

test_extensions (dictionary field)

The mapping from file extensions to programming languages.

qmtest-2.4.1/share/doc/qmtest/html/tutorial/command-create-target.html0000664000076400007640000001117511122066676025427 0ustar stefanstefan3.qmtest create-target

3.qmtest create-target

3.1.Summary

Create a new target.

3.2.Synopsis

qmtest create-target [ option ...] name class [ group ]

3.3.Description

The qmtest create-target command creates a new target. A target is an entity that runs tests; normally, a target corresponds to a particular machine.

The target's name and class must be specified. An optional group may also be specified. When QMTest decides which target to use to run a particular tests, it will select a target that matches the test's requested target group.

The create-target command accepts these options:

-a name=value, --attribute name=value

Set the target class argument name to value. The set of valid argument names and valid values is dependent on the target class in use.

-T file, --targets file

Write the target description to the indicated file. If there are already targets listed in file, they will be preserved, except that any target with the same name as the new target will be removed. If this option is not present, the file used will be the QMTest/targets file in the test database directory.

qmtest-2.4.1/share/doc/qmtest/examples/0000775000076400007640000000000011122067201017361 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/0000775000076400007640000000000011122067201022530 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/third.cxx0000664000076400007640000000012611107032170024365 0ustar stefanstefan#include int main(int, char **) { std::cout << "world !" << std::endl; } qmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/expectations.qme0000664000076400007640000000031211107032170025736 0ustar stefanstefan qmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/first.cc0000664000076400007640000000017111107032170024165 0ustar stefanstefan#include int main(int, char **) { std::cout << "hello !" << std::endl; return 1; // Let this test fail. } qmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/subdir/0000775000076400007640000000000011122067201024020 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/subdir/test.cc0000664000076400007640000000013111107032170025301 0ustar stefanstefan#include int main(int, char **) { std::cout << "hi there !" << std::endl; } qmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/QMTest/0000775000076400007640000000000011122067201023705 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/QMTest/configuration0000664000076400007640000000025611107032170026502 0ustar stefanstefan . qmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/context0000664000076400007640000000031211107032170024133 0ustar stefanstefanCompilerTable.languages=c cplusplus CompilerTable.c_kind=GCC CompilerTable.c_path=gcc CompilerTable.cplusplus_kind=GCC CompilerTable.cplusplus_path=g++ c_options=-O3 subdir.cplusplus_options=-O2 -Wall qmtest-2.4.1/share/doc/qmtest/examples/compilation_tdb/second.c0000664000076400007640000000014111107032170024143 0ustar stefanstefan#include int main(int argc, char **argv) { printf("hello world !\n"); return 0; } qmtest-2.4.1/share/doc/qmtest/examples/xml_tdb/0000775000076400007640000000000011122067201021012 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/examples/xml_tdb/exec0.qmt0000664000076400007640000000051311107032170022540 0ustar stefanstefan python.ExecTest pass 1 qmtest-2.4.1/share/doc/qmtest/examples/xml_tdb/exec2.qmt0000664000076400007640000000052311107032170022543 0ustar stefanstefan python.ExecTest x = 42 x == 42 qmtest-2.4.1/share/doc/qmtest/examples/xml_tdb/exec1.qmt0000664000076400007640000000062411107032170022544 0ustar stefanstefan python.ExecTest .* x = 2 x + x == 5 qmtest-2.4.1/share/doc/qmtest/examples/xml_tdb/suite.qms0000664000076400007640000000021611107032170022664 0ustar stefanstefan exec0 exec1 exec2 qmtest-2.4.1/share/doc/qmtest/examples/xml_tdb/QMTest/0000775000076400007640000000000011122067201022167 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/examples/xml_tdb/QMTest/configuration0000664000076400007640000000044611107032170024765 0ustar stefanstefan qm.test.xmldb.Database qmtest-2.4.1/share/doc/qmtest/print/0000775000076400007640000000000011122067201016677 5ustar stefanstefanqmtest-2.4.1/share/doc/qmtest/print/tutorial.pdf0000644000076400007640000113322011122066343021243 0ustar stefanstefan%PDF-1.4 % 123 0 obj <> stream x]N0 y ߀C3I#&*c 8QNWunaPy}^Q]v* iW Ƌ3-xo/}d+6vG]r-K1ml<& y@RLUѰY\uPJ Qy<8X|vfNӪY:e(JspEڻs%%ti((^|M> stream xڍZrF}W[*z yEvkK$*?,E @bG==iq8qf}z G,WXf-{zz/}\?pXDN$˟_{t=At0/ݐAoj._k>CGM_zYZǪ3]\2 C[՞U!:ڶG& B9z?BaNBGLOͬ(#hOB2 i{':~d:-&8*9R4զ=+< Z}giWB4]))Nt6z©mx'v53I7Q QWbUW (͔ge}DL(nZJ'aj |ΰo}au9sM>1/ ٞ)DslZWJ(Bx2[=V׻q^8bwEGq2FP(PH#ң6"Rg&rcN] !-.[VH٫c`c#FE P'?s<ϥw(*Mr eޓ{z:%E\NsOia#Y]h)5n=o8k#QqDlĪBAe \Bx\ϗzxST``5m s1u(tLDSG Eh90-@IF6hgE^ R(1dQ\l~ Y ]O}PwKi}JGh"zJm~UC&6IiD0R[-W5㙧8sٸ'W `of*6X50c&q!yٴ8W@tbNuX$8_[ΦEm_6f9@S˛O @BlgxY0p 4N v&ț'G`̮0>e<@Jp^@~}ys|w=/_*~{kNo2SAiyx{FÜsCԄ}O}C:5}X^AlikE2wlAɑG mU)hzYn7}jfQ83wRKg@<[ReH1ۘ7gk)Ǒ=Rn(P\+n'\"\hu@q]yIXdNi؝+Hdjk8´&`RbG.y_T& gxQV癀򖵈ôqZ}7WY'@EkivyϰYZ@Icȇs3er ՊP#V\vbFqPճUsbhc?|z}r!$]&)BLjyEq|{C6Xua-\ #ToĻW7w7ѤH}.4K -eWSeymSYho@*dK .}be޾}yQ QK)ޛxzz+so8 I塴qY$OI ۠Mw؝ʇ}B@ \)Vfh<cth`ڤ;mF:;f)}iabb {s.sLg(p2|Ps7#p ݬХ7b 5M5DdD4{団m`]cƋ>MSډ?2E51ڡL1fnqi6<ހAxyv?9DCv3UC!v4vƑrD]in#Ri*s.% O6fg S>ҽ9hf(Y5p~xJH1C1쐻,wSfzaJ [brb?LX,_Obq~kK&"u%i68̱SziK^[_0}Sh^/\.gx7b;-004z"~|xMLt9a ޮ::-^%i 2*Ϻ"E0 s4+okygyae;#.ώDwݮ)T, r8]\> stream xڝWv6+s|3;qrpj"! 5 QEvOf;w\2<^ro8Ij'<H}Y e c_z+Nh"ǖl+M -ee4걚4bNOҤP&ʊ6WՖFT^~MDevuQo&˥5,.̧qozed/Dq~5)[mH) lps@#u?Z=x%4iĜ.?1XB(qlct|ZBe=n9%4US֭q܅ng='T^X^ #3CF!~wʨvIc;ɞ+<{#l]mRX_FmUz4mkׅ;!bź 4BUYV7sJ[>IU7',UF2e: ȾA9 ޙ<ڣS>:{Z[{s瞳3 #$4yQv{RR>]iJqXh-+Ł*8#ѐ7mal h(ޚK| Tf 0N*2L(q[s$oWwݗnF[qB?<0:""UG;o#N0[+#52lNY#$5J_aȇ0Z;8M-N# DGY`RB،c 9-$pz~ph"_mKCꇉW7@";YwZ]u`qݑKl(]LJƩ"W' P2n4CWm !SHiǀ)>Ohdy;50cH!ɪs@9hTM0uvKQ:kQ<rX_R ár"%}sfJi O"Ùkw]<Q⨥ZV6Q+_zWk% ϥEr5pl @7Fzb Y x4Ix|uF<1#<@x8tusLݯh*X a$@eͳ.sp@t1Yh(ͭƈlWY9C}^0-cձ5y)L[Na|{X9I<&OL"?`oŏ)Z/"bG,q-&lGendstream endobj 139 0 obj 1483 endobj 142 0 obj <> stream xڕM#W&=E,D;s?niclVv bdz@He}=3)cq{wSe;rKu??v_q$˿_>+<»>uykzNܥ>o_/.x(yR Ԧ@(dddddddl'RHiS h @2]R@!ɐdH2%LI$K%ɒddddddddn@Sy( IT@!ɐdH2$LI$K%ɒddddddd|">sKrS;ߟ> nl?~x:p8}y|Ϸ<9~ _W+555uuu MM͵qo>Oy|wԬ ~ _/W+::::&&uY~mp;Ys~_/+ ~ ~ ~ ~ ~~~~~~~~co8rλ%ouw[2Ϸ%ϟ1_O.׃eͻoPy >LpM(:p rRI$C!ɐdJ2%,I$KMMMM]]]CCCSÐwoR%QCQp}?O>C]r?;x<_R;%@S`"pN@)0O  I$C!ɔdJ2%Y,I$$$$$$$$$$$$$$'$s( $s I$C)ɔdJ$Y,I$$$$$$$$$$$ɇ!2jݤFèuy&Ǩ/>zzq;jm M.@ST@]]]]CCCSS3B$gp"8MyDLININH'@S@)cD dH2$ I$S)ɒdI$$$$$%%%9$9$9$9%9%9%9!y <NRH'@S@!ɐdH2%LI$K%ɒdddddd|"0F7ɷs߿7kyu/O|h"Sd>?,>?6,eby8_]v+eby^8_/K%~ _777777~y|wٜX~y~_/K% ~_______߀߀߀߄ ܆ƿm7/1l.~C'BD< P B!ɐdJ2%LI$K%&&&....!!!)) cNA h @U( y+ I$C!ɔdJ2%Y,I$$$$$$$$$$$$ɇ2ܤڗTl귫yl6y>pt~W^c=vxC>yR Ԧ@(4I6I6IvIvIvIIIIINININHs?$P)cGdH2$LI$S)ɒdI$$$$%%%%9$9$9$9%9%9!yMHs?$T@!ɐdH2$LI$K%ɒddddddd|"0__þM!ffǟ~Nmkw|ksn.  Me`ZJI$C!ɔdJ2%,I$KMMM]]]]CCCSS_e h @ 20-$C!ɐdH2%LI$K%&&&&...!!!)Da <(I?iлjÌT6HaF 3RmjÌTf0#Ն6HaF 3RmjÌTf0#Ն6HaF 3RmjÌTf0#Ն6HaF 3RmjÌTf0#Ն6HaF 3RmjÌTf0#Ն6HaF 3RmjÌTf0#Ն6HaF 3RmjÌTf0#Ն6HaF 3RmjÌTf0#Ն6H}ˌtoչ7Щ݊wO>pLH?}z2_lw<ցP)08u#$$$$$$$$'$/$@*2: 4 yY(YJI$C!ɔdJ2%,I$KMMM]]]]CCCSSUu h @nl$C!ɐdH2%LI$K%&&&&...!!!)Da~)&9g:aoQ꺍r7^ oʣ7Yߔ(g@_. MH^>d( yLu dH2$ I$S)ɒdI$$$$$%%%9$9$9$9%9%9%9!yLu3AցTYB$C!ɐdJ2%,I$K%&&&...!!!!DaV"mH$Y,I$KMMM]]]CCCCSS $B$JI$C!ɔdJ2%,I$KMMM]]]]CCCSSm MHiWd'RI$C!ɐdJ2%,I$KMMMM]]]CC qrpwSE |}?~;@GืXBDืXJ@J2%,I$K%&&&...!!!!)) ˽: @roMH^-ցR@!ɐdH2%LI$K%ɒdddddddb[$/@* ɐdH2$LI$S%ɒdIIIIIKKKrHrHr<|aro1oN_ۼ`__$ey{??}?; tG 5c_ s}~Wn}^8o9:::&&&/_N8Obp8o8_/K%~_7777777~p8_iy|9~_/K ~sy @~RJyכzR{.o?~;?R@y|ϏW>?^X'W+ ~ ~ ~ ~~~~~~~~~~swyܿbyׁ]ցR` p: twZBIINININH"$P)chDdH2$LI$S)ɒdI$$$$%%%%9$9$9$9%9%9!yMH#%$T@!ɐdH2$LI$K%ɒdddddddx"0Fo׉tz8c8ח͛טwW777777~Gwa}^8_݅y|wts~_/W+ ~ ~ ~ ~~~~~~~~~~swt]X~Gwa}^8_/K%~ _777>zl<μ ]C-/u>] Zo_ /?z6.?JGc7%e@G@S`"pTwIvIIIININININH^J@)KwH y@S@!ɐdH2%LI$K%ɒdddddd}ׁP)Kw($ I$S)ɔdJ$Y,I6I6I6IvIvIvIvIII'ڛu[<<0}t???xT;_QMW(B$$$'$WH y@(?$C!ɐdJ2%LI$K%&&&....!!!)) B$W( y@* ɐdH2$LI$S%ɒdIIIIIKKKrHrHr<|&Wn|5}x.@k" HrHrJrJrB5]RH^@(k I$C)ɔdJ2%Y,I$$$$$$$$$$$$$'$]E h @5]JH^@* ɐdH2$LI$S%ɒdIIIIIKKKrHrHr<|5M5}xy|o8??]CQF2pT:ׁR` p:ׁT#p;ׁP@r:P @\RH^*@(dH2$LI$S%ɒdI$$$$%%%9$9$9$9$9%9%9!yi$/u h @R]JI$C!ɔdJ2%,I$KMMM]]]]CCØw}yN owaÿ_Gm_r8@^ t?/$9$9%9%9!yy6H}>:iƬNywC}8y|w<\'~cy~_/K ~______߀߀߀߀߄߄\q}8o8_s~_/+ ~ ~ ~ ~~~~~~~c'c6t1cn/p9f(o1@*x[YB$$$'$1@*r" 4 y]YJI$C!ɔdJ2%,I$KMMM]]]]CCCSSE h @.,$C!ɐdH2%LI$K%&&&&...!!Drm:O~y7O~rLh9&Z -DŽcB1rLh9&Z -DŽcB1rLh9&Z -DŽcB1rLh9&Z -DŽcB1rLh9&Z -DŽcB1rLh9&Z -DŽcB1rLh9&Z -DŽcB1rLh9&Z -DŽcB1rLh9&Z -DŽcB1rLh9&Z -DŽc⛗cn׉}8u9fr̮]1cv-Zٵk9fr̮]1cv-Zٵk9fr̮]1cv-Zٵk9fr̮]1cv-Zٵk9fr̮]1cv-Zٵk9fr̮]1cv-Zٵk9fr̮]1cv-Zٵk9fr̮]1cv-Zٵk9fr̮]1cv-Zٵk9fr̮cnʊ\wOK7/}?˪xܝe|20|2P . ,!<@)/ó Q<@(dH2$LI$S%ɒdI$$$$%%%9$9$9$9$9%9%9!SzT_>ga=@) ɐdH2$LI$S%ɒdIIIIKKKKrHrHr<|/N$EQꕷ|X\J[rH:oE h HrJrJrBZ\RH^땋@(^ I$C)ɔdJ2%Y,I$$$$$$$$$$$$$'$E h @Z\JH^땋@* ɐdH2$LI$S%ɒdIIIIIKKKrHrHr<|ZM.s;O~KoE+T#V\BIINININH^땋@*kr+R@!ɐdH2%LI$K%ɒddddddd^MH^땋@)krH$ I$C)ɔdJ$Y,I6I6I6I6IvIvIvIII'O땷En'oW^ay^z" tꕋ@( kr( yW.$E h H2$ I$S)ɒdI$Ylll+Tz" 4 yW.$C!ɐdJ2%LI$K%&&&....!!Di6>^y<c"e|m^MoΓ݅R` p9B odddddeZ_JH^u eZ_B$C!ɐdJ2%,I$K%&&&...!!!!)) ˴L@(eZ_JI$C!ɔdJ2%,I$KMMM]]]]CC~mԞOkԿ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Zڧ}Z۷Ooyiyڧ1>i Oc}h@4ڧ1>i Oc}h@4ڧ1>i Oc}h@4ڧ1>i Oc}h@4ڧ1>i Oc}h@4ڧ1>i Oc}h@4ڧ1>i Oc}h@4ڧ1>i Oc}h@4ڧ1>i Oc}h@4ڧ1>i Oc}>I^'Ώڧ{8}7OR` pm>ky {y{y {y h H2$ I$S)ɒdI$Ylll|o>|o>MHOJI$C!ɔdJ2%,I$KMMM]]]]CCM:nvڧu6>y| oޙy:D< 4$9%9%9!^|H ^||O> I$C)ɔdJ2%Y,I$$$$$$$$$$$$$'$@SRT@!ɐdH2$LI$K%ɒdddddddx">yΓ'Os'>y{͇灷"P ꓋@*xO.$$$$'$E >MH^듋@) ɐdH2$LI$S%ɒdIIIIKKKKrHrHrHrJrJrBZ\B$E> I$C!ɔdJ2%Y,I$$$$$$$$$$ɧu>yne'꓋@)0xO.@G>'R" @Z\B$C!ɐdJ2%,I$K%&&&...!!!!)) k}rH yO.@S"P H2$ I$S)ɔdI$YlllO$'o s>yj 5y}W iU<^V2p<\JrH:u : @r<\JI$C!ɔdJ2%,I$KMMM]]]]CCCSS@(:P @rH$ I$C)ɔdJ$Y,I6I6I6I6IvIvIvIII'˛~yU~y{ɇE/T#V\B$$$'$E ~MH^뗋@) ɐdH2$LI$S%ɒdIIIIKKKKrHrHrHrJrJrBZ\B$E~ I$C!ɔdJ2%Y,I$$$$$$$$$$ɧ~ \@Z|H:@( @)@*@(dH2$LI$S%ɒdI$$$$%%%9$9$9$9$9%9%9!^|H ^||_> I$C)ɔdJ2%Y,I$$$$$$$$$$˛u"<~_nr+[/w<]]'o MyxFH$$$$$%%%9$9$9$9%9%9%9!y<}RH>@S@!ɐdH2%LI$K%ɒdddddd1# @<}JI$C!ɔdJ2%,I$KMMM]]]]CC &y?nn Pa*[Cukn ֭º5TX Pa*[Cukn ֭º5TX Pa*[Cukn ֭º5TX Pa*[Cukn ֭º5TX Pa*[Cukn ֭º5TX Pa*[Cukn ֭º5TX Pa*[Cukn ֭º5TX Pa*[Cukn ֭º5TX Pa*[Cukn ֭º5TX Pa*[Cukn[+7.\wOg3әutv:s:.MpQ9݄ӱ O c}V6}~892}~^8_]+kky~_/K ~______߀߀߀߀߄߄\]Kkky|wm>?// %~ _Wkkk=?^~6^7/˷ݿ~wrl/㧇W%x"ƞ^ouzU: ~>#NͯKK?kwendstream endobj 143 0 obj 11696 endobj 249 0 obj <> stream xڕKsyv} <^s{HM7=B6Mg]@YBaHff:ܦ͛ͻ/Owt37Ns웚۬7v7t>v:}pwpea֧Qw?[:̿/vyo/g${ֽ&ttkk7oh?;Lݠ'tg#~~~~~~~~~~~ ~ ~ ~~~~~ ~ ~ ~ tеOG]q///////=_4QuQ8tǏoy\5rO޺?z~t7  otwot7 ]ß   ot7 ]ß]ß  fac0Ov5O?} 4^ŗl/>_=Az>_ݠ_~C-ewo<(AOo<({@???????~[.n[.еryPv~~~~~~~~~~~ ~ ~ ~ ~~~~ ~ ~}o3=N> : g#l;tgt///////o0Awϧtе:9999%%%55uh|i<{~1i;3н '_}^=I|_{e#%st6S!(r2V+VZZkjՆVZmHF]g(:KECgfZʹi5j\V Z-ZjjJV+VZZkjC 6㊢Ȧs,EnȮV3fZʹi5j\V Z-ZjjJV+ZZ_U{=v;cγcNz^|ɫ+O$C/: o{@~G>n:999%%%5555 7|Qw櫏櫏t333ssss KKK++++kk~ˁ ol<\2< %7[2%nMy_=k]͗t7    o,C~e1 zB~e1:9999%%%55ul|YvΕ= ~ ~ ~ o+{@~\[nn:999%%%5555 7r;Wv۹۹t333ssss KKK++++kk~iyn]M݅[aao%Wiaoiao;iao {=k~wP zB??????~;/w {ݠ'tw^  zv;.] x߲&ž\s {nraM.Ʌ=7&ž\s {nraM.Ʌ=7&ž\s {nraM.Ʌ=7&ž\s {nraM.Ʌ=7&ž\s {nraM.Ʌ=7&ž\s {nraM.Ʌ=7&ž\s {nraM.Ʌ=7&ž\s {nraM.Ʌ=7&ž\s {nraM.Ʌ=7&ž\sㅽլu_سb"օ=žMza&g^سI/٤l {6=žMza&g^سI/٤l {6=žMza&g^سI/٤l {6=žMza&g^سI/٤l {6=žMza&g^سI/٤l {6=žMza&g^سI/٤l {6=žMza&g^سI/٤l {6=žMza&g^سI/٤l {6=žMza&g^سI/٤l {6=qao5_y\L&N3o?]LBk}ǻO7?5?̋pw[ϟ;݌ZtЇ{@o[dwot7    otwot7 ]ͣ  fzͳg#׏wǧ~o_kO_/j؊cƭ.殞eoKyCvе|O~~~~~~~~~~~ ~ ~ ~~~~~ ~ ~ ~ 7ݠ't7=k  fg%8hOC|_^@3(_n;~F>r9;Pw^~n;Pw+kkk7o~@[еr5Pv///////o;t\ ݠ't\ =______________ 竁i;q4n7ż9]|Õ1o{ևcKiJwЇӔu?t~/е|Vwе|V~~~~~~~~~~~ ~ ~ ~~~~~ ~ ~ ~ 7_ݠ't7_=kB  f8}c_<%W/N2N7ݧ?]lۑ\N [w;= zB'%%5555 7rt9{@oOK~~~~~~~ ~ ~ ~ ~~~~ ~ ~ ~ oyx_ewoyx_v///////oewoyx_vе  / ܼBɽ7}8ի}owo$W>Qg~]dq[޺ݡe7    oy]-ݠ't[~~~~~~~~~~~ ~ ~ ~~~~~ ~ ~}o3<_}9<.(fWg~׏3|x>S4O.NW?wmϵ}N}yNv^Ϗnx//////oGd7 ]-е  f`ym^< r_/X-v>fX|~qn~n='do'dw=  oyrOv'd7 ]-O//////o'd7 ]-Oе  fl>ثW۵WoDt_]w _|+UvK*Ωy~ʡVkZjC 6FaCgNXeY-VtNi5j\VsZ-ZhjRV+VZZkjZ 6ڐj Uv`MY-o V9tjLVsZ͵kjBVKZZijZVjH>_Yն ګ?SmK77t#޲7twtno//////o ݠ'tw^]C???????:<8{s-Vɖ#6+li{ly/ow7dvK-My|}%sZVk6jC 6c9tj=6]g6_tNi5j\VsZ-ZhjRV+VZZkjZ 6ڐj TvMY-oZP9tjLVsZ͵kjBVKZZijZVj1t1mszԜno?ϋq4x6t? ?>d_^({@~kewo)AOgggWWW7o~}N[sn[s//////mF+Wk9>ާ_I&x|k>t?uOKK++++kkk7oh;^ݠ't|kt|k;t3333sss KKKK+++kk~w^8__u/Owޗ}:i}ܫa=N;}~Iv~ ~~~~ ~ ~ ~ oyIdwoyJv///////odwoy@Jvе  f>ߋ[Oy\Z>1zY详k;78M7?riAWv8ygWf۫eU1fH}JvЇU//////o" zB~Z]kE;t3333sss KKKK+++kk~eeNy1<266Lz9n'>h31ŗc̯?}rn8u/Og zB,{@o  od[>,Yvеaɲt333ssss KKK++++kkk7ohÒe7 ]-,{@~ˇ%///////mFc=]{ݾhzW`7߽OY P'ܾA>u_ C/1n//////o1n[^ {@~ˋdwggggWWW6gՙv?8P:dz?3ۗ$O}Kkd4AwӇw///////oλ;8~7 ]?wt333ssss KKK++++kk~λJqw9zd1Y^YPzd9Yv{@o#nwyd=______________~C=,ݡkeG//////,rq{e]\.W뇷p2>/{>?/AOCQ|zWWW7o~ˣ;t7bt_ts9tnOy]ttNZhjRVKVZZijZVZmh!̦s,s̡TO2Zʹi5j\VsZ-ZhjRV+VZZkj}U|^ˏGpP{O?m~:ƴ:n_zm:T=FV5dmUOUuYKoaUUJV%JZjiҪՐVCZ i5@!ReUVSV)2ieʤK+V.BZ i*UJV%JZjiҪUK!j^WeUV}{UM֔UYU YI+V&\Zri*UHV)RZ*iUҪUIV-QsdC,7|eUb3]*ObxDtKġJhy1TB4%(QJDS1UTBL r%JȕP(PBB J%JP)RBZ j%4PBC󒈮%MTQ̓2%dJȔ+!WB\  %J(P*TBJ *%JP+$>+_C/w>ɢ~|5 d1겖 NU5e*iUҪUKVCZ i5PV'*c[EuY򙭢)2ieʤK+V.BZ i*UJV%JZjiҪUK!j`VQ]Ve|*&kʪOd5dV&LZriʥKV!BZJiҪUIV%ZZkVGy,|9z>o̗9C?_tçݿ?NfužDw<..~ Ǜ?xt[x)?ǯC;yǻ_w|<"Gg> stream xڅOsV?vm9%t;p'i~^9#}xlK֭/na?n?/OۯW.2rٖrXv6׻gt6Wz顿N}YXN=>^uO#t~~~~~~~~~~~2e+W_ ~~nе ==k?G%Kgggg/_ ~ ~ǗjEޯ1櫦Y j㲛?^vlջns'>y'ޮ;{n////_ ~ +W_~l;tgݠ_~ 999e_rl&٢ä`dPE{㠐NDŽ]Z-9L D]ɪIK^eߏ";4nг@"{/_~~~~~~~~~~~2e+W_ ~*tWdOۏ,;tK/____ ~2+W. )Qf6 2G?edayqzUtRس[.*4Ћmݠgz/_~~~~~~~~~~~2e+W_ ~F FQGw~ %3333sss /_~e!f?̆QgH矦Gpcٽ] ;m>o4\|^i:̏ۏG/ۭoo7?avmCϮ'ޮ;"tݠk{еtݡ_~ 2e_rj\:N+_kY{;}7v>=l+۩m>,6,>_MN CY9;6vǭxx;ǭa4;ӉalTcm!›?Oޢ}U0_~ڮov6'fb:k3,bg[WWxݴzendstream endobj 363 0 obj 1403 endobj 378 0 obj <> stream xe0 w?Gv4 &H̨*T[iK(9b'B> stream xڥZm >Bߚ%oCC (ώs{◛߇ٻ wMQ$E>|(cy"](q;)BC?e"2HR?۟A U9]+.}5T8Tkb~(F1oJ|u UVA~n];E{g=ܴ?2ǚLL|VMZ7xDTb8U)ηL%*Љ\֫< f[zqe(e8j܃X,T.' C (ba>t&1^ƪ=LPB+ǤʃX6kn1J|(.. \3 e oSEED۲l޼wY!&d( ڥLG#eRJu\ԇʄPq4 -bT8OޔfYEi݅Wm 襪f j*6t5L8Ľ A*_u@|' _yrF%'SRqb8uScbSS ǹFAuhVɺ<-`繫sAHs_4Z m^Н΢|Zq m@vR|m͡ƩS ޜa(s3,}er6YaĆUb*Hu8U5Gž-7g-@'ז+ma@Ly^M>Qp> v'σɳ P Q;sŰ6EakjBP~zgQCTM]üUD0;BRWza6X7*f6 ˜Yְc,Bf:iNä. KMǩy0lI\|N!RC1ZSDWkL|]7أc_ c?#a)pm|:X)/Rr"@[Ih!<x4gK= h9`Q %[`B] "wP#6%Wea87zf}u0 ׊|]ݺ-uʃykN&f ͣoǮi88rorW3xZ+-j#ƿ-6N G+ԩT+éyoγ O7WyǞ3Q5 ³ A4_јZA,}=&.jBLp.wYy~g̉2qOњ]{fwݘj,BRaJF&&xdyڛ`yy.;zo&4d yYh3H#eS3W޿TM: y9zGg1ahU~^'*? K5bޱQe^nQUoa@}г|޲Lgie27JY' *dUXZA.W{}y]2=#rad_a^t,sO0mX[|[}5rNbΆFfyӼMHv~E ͽe0 . +*p=Wm~uOرh,t4tS_V2}m.}R?A!n [pA9!߾"wJB<׼+"&}7{i&T p"iRfi/ ΓA7TrswQHT ҪsKIҘo&`t~23:Q;9i_`縘GAƾ-o߀bmSiy1Vho:n|;\<_soj~Q-%8t쯬A (cqGWS2V.}}_:Z$s.TE69[旆F\D۶}D@XM>|m~G;tfz"ՅBDu95Ee:zE :Ѿčoi aڢ/\IpObs1 Q;(T,&SP78 NF;k}c:$Pl(wyL'}I^{RRo}Geo{bшazm7vgЍb]2:k/0 iM&6]9ѐ}w]qW$Q T4N]/ ysKas1b`\d+K'G龬'ay  Gǽ7kC2FmgZ MmayAV$2,N[,rIIDYiǎ/yIK0ܞBIkND ]\endstream endobj 383 0 obj 3011 endobj 391 0 obj <> stream xڕYK6 1CQR]Ϯ{`!Ki%zE3~n:bXUWt@E. l,w?vaz1+&cTh?4Iw?!h"#W蹯t5N6tzU&( vJ#EN/H"`iHQ.3mHsڃ[u$L!yq ͑;@mSf'Q`4QrJ= )hCWi14J+VRX h,+ %?JJRMUuN?06^ϋ,0EvrM\xhZeQo#vjq.wnZ~-rphiw0i{=9&\\Jn\u2 .\[wje}d'n(v38 ؊r߸'=婢F}*y^2:뻢~& Wl-6.K[e;z˜Si g(b4}=uQ[S~aFt>C}2YS91]pZC@]^e #yG7uY3Vu\j{0c=/dBQdIgN٨,"'k^ Y1-͖0em) hY^/X,qqlʲۂXY^0Y-`^ŃȖEg[TziiA`Y Ʋe,A@l7?l{XEwiQnc{[7bTdx}8ɡARo]HkX/wѧ2"F#?y 땷eyx(ב?~n:۳!ݲY߶{ۈ. US#^$i 19Y©b xY]R9t:r!Ѫ2AAvE^'kABWvUU s5\՜CZ92W{bvi$4 -q_IcgsD:*1X[.!tݿu+P@7P+=)Cg^CmuՒ+`#(iΖg@8>k_c@8pUg#r\Lǰ, (`Ew"#Zw9)f>a$NӷoIL~%0'U \Ձrmh^A۰+m3v%.ת.i,wӰo"! '{_?,a~T%0ڮNBQ@ w1e;iDeNc yf+K/xJ}1hBxS7%%8c{o2g^7zO.w}{<J^_v*3\gf(tYq|#YHpzG$ުj|B[b[KA/R)S8׽54 X<䓴bfwT$/Zu0#Bf~IΚܴCaxMS_L&v`GΩc$ 8{^4:Uxh=̜FoixR^ _ιր #0GX1F"%qwm??NJr>ẗ6p e+̝>eOpt[EO}nbmϏJ׫²>ԓR*HE'@*..7E貴ym$Xr}un NLO i*=S#{v}5_- '$j@Azk!}CD~: 4 I6}-s#yQ/(7$lT\Ag(Y` + ǰ9Fy-ٓ@ )yX+?Z°|AbHL{Nt0endstream endobj 392 0 obj 2325 endobj 400 0 obj <> stream xڍZے۸}nd.q!)OK8[;T‘)R+O>BO*d4F_Nn]"˒ݻ۷_ǻY$;d}'iQ&o.~0TK?%OI4 r%SNF3ɱ?7m*w}I|in9]`ZTxSsԾ0|칻:Ty$,YГ Le| 4֟DϋP S?]di̖i.u(o^ȴlLR٥NSSAݢbvѮOOuw0΂%[Apf,E J{[>7m\aH*=S{L*27 f4IoQT7QpqswB{v= Kɜ C{a_v% ;ܿvϣ,=|,_4pJ-~Y٦Po&z9պmS d{\ر߷vذ+U(QL#*dl8J3%B]2|9*߿z[W8БMA2W*Y"_P)VfMcKN+w]?, ߺ O&uR6h 9e 1n>D?Qs d>g0Zf΢3ɩ&>׷V!E/ S@VW\=;l)_1 Mw&T**^9Nu&eW7l WX›kn\`V r2;5"l݅y@gW+MG(U*KɤyD v >[X\֜=/7/ޯ{ | NVeRi[C8R㊭JJ_=O=^GYF3Dfgchs% OE6{^ܐk_ވ3C(M\LQX-),PRA35zz%r&6f{(~gh:W !Њ1*3,#5؟89Ixc@@¸jIS~Oh.lr$ 5CQ؜B{( G'QS2K&ȥ {eVJr1=Sͤ+ .sT*91GR͖}m? `NS&?L)+ YH fr06b[pk(7T r[YP.A90–Ss.L]k], #_|OZb jEݱׂ\&8HvJ(X>M>Rr=7TWb֓/)'6F`ԭb(dV+䷔Z0==ʸNU1l 1v҂~juvPZ5 LLd6SbԱ:xvHE5xչL˂K}afJZMUg)ܶuNLpN=12yv5E`막b^VŴ-)kUf ۧGRd,P9NāW@A׎v‹І=y T8x ᓇX2B K&*VH IIs Mo+:Zln1Fw׹]YF-4 \M}\ Q>K fX_d2VY@|[Cm'4LEx7D]uidg2WITK\QS6987'yN֥ᑈx8΃ K9 b.O7GhMMv2Mc mHp6=R`'nƢ_@;ËR,DP +Ϧo?vN!/8G/LN/n#ye穔V)^¨'NMeD߿|4@=6~\*$/!8 HBSfvļ_IU endstream endobj 401 0 obj 3028 endobj 405 0 obj <> stream xڥX[o~ׯؗ&r7?pZ'@zU@AS͆"Ro퐔[ ofgf纞X?<#W֫o+vx󵈔a$ֻ՛[CižɛhC.VTAUV7[hÌx&ȷ뿰?ۋE'gxI+OѤòǽPԕ֍\[+kVX!xx[yC%wE^TnKb@kz^[@`o<3e $ջ5{Ԟ~BDzYkŚ,;؎qt{k29MmB]d~L4vQ$$։W |vMA"=,k>C\= lQTAS1Gs+uK} `)M9fZwgcu?搁,/6C@K5 iKmWK,7xR=gND4 VH#wpn[^G6:۴8$7\Lr;Q$DGG.BwpΗX˼؇~!h\^n× ]B4i_P Y Yv7sO9dN.#sn<-]t/sʓcjő2c *I>=4a( cɀ)·,Q7KJo.<ЌDrpHY},7|ȳu-Ҳ$U&GE^xH-| SF;II"),\ tJcF$|go?>PEӱ溆y=WRz>J$tj*5d&Q6Egw0kAB@B򥨏mU瑏yp(@4/keY1ggҰk:#48?CY!;*ԭՖ_1ݴdD - L! 0p,𥺢z1S奠7w\߉턨NB_Ou~'s%ޣqDFB|-_hW-`>\QQjq<qTᒩ`L}^[?znjjwqxVH'L7hw'\:F. ZGoqܻpf6t7Pzݾ*?3:Fu J*/8W&=<8\^<ήו3qLDۼfsw[>9(17 /5'T|AOwn6_J=ipܶ$TlSXĉ>I3=aٙسk~LSe 'qm610V'Ъ75dM^r=U'.Rf e|b|xzݚd m$d0_OTŻ/㓢& ÑKp;m w!> stream xڥY6_kVri=+h?8hezV=9ܤ$r8/Y`y$[9o%o_ P,9~1:wmմ,-wTF qHRKhytw4(vW(ΞRu\U*[–t1[VMsOgiɺFeզm^ 2q'A\ڊ5mU+z_G}O[v΋?l5\5F٫&H#}xS1a{O;Ci:].x!|:yڬ:*5KY \J<9ah.j=*;!y$lZTM,o\瓈"qlC5+;LwmW_C$(Mz .h&2jHL;PziӼT;Έ2O$tb\M- Ҿ(Q#$k^;poz#pLU܍mx0:eZ2/_8 '@{B#GMԵȯ";l]߅cM6oMuyKǽ&>R]ޜ7EUʶ|;7 #xx]mPpvk?RȊxdjOYGk h?!KWlf^\Ӝs<4%mپ{l|fd}#ӥ=Ti^e=>-57 GGNFD)G/F|Ѩ-)iϛ7]_L[Ts=eCMk_PpCh|\N8?sYovg,}(\0mwtmZ| EO_#v,|LS2H6e,W?TDcV* pqg L4 צ6j-t=k_k]u'ZBR *5#)^F@6k{0ScZjEY_`%y,cfT pW! n RF3SMy³Y<؎EYU"`vugߢQм4 _Lucd;dErqըWCpXd;$-.I7"1 T6/ƇCwb>}i!:`vD' =Ʌ$=}om6tʅ/ ǩt;1SI>܅K\~hה JjDx6Fwo#:¼HhD͆· dN(AD$y!)= uoߓs?x׊ mQlӖVyD(=Y &oG;9T]VV2Z 8'%'x}L=;¼<#/L6mvP}YL=Jm+tjc;^”d;)HXg +|Hρdt+Uiv0P;c"m%ݖ}4jZ]T=3B}T 0 l!Ta􁈉Pkx/O<7NNU@0,\eQ\3I+l4\5X0l*pGQt9ItFtk9;q/ɘj:NOWC|Ȍ^k/b|O{Xfc\^@gѲNl}ԝ~7T|o%-QmG#akϲޡ2#Oq-ai/]${w{k"Dsٸ>˸7FZX oz O}Y}X!WѢ{b8sXJendstream endobj 410 0 obj 2222 endobj 414 0 obj <> stream xڥXKo6W8l.zHza[=4BX,9RDJ Pp8H_f<(PQl&pF|6Ξf^~ X}(BE(2(ǜ2ͮ, ;UUuZ2nҒ"}*-<92c-r|+x)s?}U 7I7n|. &8fYoM+fYdŬ!7tcpݱP<8LjY[UR)U(SU͐`VR dNTg%ZN#5r=BQ3! #Mt 0 gpFSqM,/ eH3 Lkð פ=G&貸eci%`<,T(t֨:Xa}~yvDfYp0$́#j7M nvTFe@ݩ{8>2>2ޟDhOL@f ?%$ܞƛ`[5ByStՠtxGy #/yT3tʴb6 dW&#ld01Xă('pfesɭLb}Mej|a"hq9Гw کHBH!Fœ e(*=᳌˽,o^8P+ՑbSWgb` %u ]ƘD^? aĨ\cT'OCI Bk(I31HҎ~D^CSָ$> stream xڍZM8W9enF=,Nfvmu[Yr$dIa,ǫWDb{Db?H\l7JDrEF棒oߖa[IJP|5X>CEtn NHFYІO_PLe2c_tk5wO %A%sDE7^TXu5H5)U+Y7/2F%Ѕ/N=w(ũzwnު0[)Ud%f4w?]E[QkzơbD4u{[ǡje`s@ep.,P/5vR4ISu_pʕGQ,M=ˡı]sW1Riu =(ؐp~U!_Z2J܊yͥR/Mڕ*0R׆(Gd}Wǭodq ,flq\ dHznFˮʱ=b^;?o׵oÔ;A#n"&Œ.]C}qɽQ{!\g~J]e 0#q]Y)N/3Y[3ߥ{gT[qFS<Ĕ=!9VftI4 "|t^lu& 5'5'a C$R2xj>8f! =ɒs~%Cwnm'ڪS2:i|+zؿ1 LXF LB/volO)>3Y.LjBizȄ4TJI vڻ] ݱJ;[QJJsC2 crS Hl)&MgAk"O#=9‚:vpZ|tE |q&o`9iEx e&i2$bT !޲gbO48nXl*k_l Pܢ<[= =S33k.׃2?rJ ܸzRg{Oe ,3lK?tJP% e۴~9l ;L)iTL?$&Rgw!BvQ,џO3{,nsPC~T4tp0 BoK/ֆ`Xu @")4|/-dP3OJO\6i~`)V,񅦘I˨xV{:\I"oۊ4 Cya)ea뜖Р-QLa_ju+[DJtCwQh瓝oPyA/plL:DFWeNLо:U~6Sƀm***TJ2.P7K@HjvF:rbL^%4k:Tc{9̉&p8ջo]@=ô?W&JF-(R6ȓr~/ ѓrpM8 l, Ww|?ZSphs/{ƾ( +pV)T~ǀ>91/iBKS f ӑy[֡M&w/։FN V)/6,iGh(kt, Ԗ8 ӫkV'qz+Eo5]|RFʹaaDž3K"66LLCjܷ gV Dn"{I{D~!endstream endobj 419 0 obj 2971 endobj 426 0 obj <> stream xڕZiܸ޿𗵱mx8@X'$w2Qehߧ:%uۓ]PbW(3"  `[ & )yK(E^Yַ@o3V0}x^ޖz.Ԯ =T? lA\ Ѓ`QbB^&Pvce7D[j~wS_Ngg :nj A*?uWJ\Hz}-{Gbu W@MZqdMi8ZUDEj)czvvc]h৏CoB[wmC/ ׏1c.SlC֥U];h`\cٷv;$RL`@;MtRS0)Bô)#rˀH*%}ǣQ9`Ihymg}q;unxHN$s0Nɍd\Ysqr[ul r Wf 9b2lI8N47Ҋ$^d*&ߦΎ0SX׿TJA4W RB}_&F:Y>+%<ٿW$ɥE+.%1>`Q/:N KQqL[*50goOڷHR7nق"xQ3~*ycV褌:gˆD6 N.l y遮G)>M%wP7'!5߃Üm9:YdJ%3a_:Pē':$H I|ĥ`=*9W_{!miBM"QCĒf@h FClp,<^y#$Ea}^\AQYZNekⓘ4>P!2wίcML\>aJ0c"ՌČγ E]өjّ$ESCV**^QcTM2U:*kv?庎A蹂́1 L}_B+mqgb$+%%*7WC=yO3ڲ3M8\.ȸPrth92R#CQ#ڗ^p\CK,Ir"8;Jr̀Ɛ$ <.#H.Y+X ^3*c9MX aٟ_ LEI RT˘DJ%jB}U[ov)=Lbwfx@{|evVJUZrJmAǪQB,*4^C/"<<u21WHCHLj#}s.񥱑56&RWsTs k+KZ.)$jӵiȖ=-mW(2FE y:pDd, %V/Ryu;o}l|h9B/="#Ieۖ^ ʗ/ÉruÍpɗA& ^LFn0XPcjv>5}#u"M0,!8]6Hyo(N{˴(oo}>HvA`H$ə+YwJ."msD0h݁JB_ld+ 9(# 'Bo٥- ˡ!R+{ZX9^LD醃cO,U=7Ȕ1];k>-6!VUXNjz}/:$t~/Ɨd3X\̿"# mzԕ;n* o߾RZCWy/D9k&y LȺ] O HRu@$eC"70Uwt {a8|:m!K|̢qtY98Xpol ̊ =W[5`UNMg-%;0]E;ϑL:\F:}ﻴ]xwIAt.&Ǟ}["uN|ʸX }9EиvOx2 \ݩi>秗^a<~- [ 0fw;c~?G> stream xڥYmo8_AKR"=-EƋrduW/Io,A/E)9Ùg\lp:Y_~i݂3[?`|qMmZYYٱCiOxL˶fD -Lrb̏i7iYYGYn, ӭ@A6ΞҬ.sFmhYtCf[Ѭj Y.45{Jۦ;E7tvaqEȷmrÈ\ȝ¬.١ pB_Ӟ0rkPlqX(IN g>DC.jN ΁@".g3IF{@]>gMNՒu;W=)o; 'I}u㒹wԛ̵/ x-,Bʽfykxg??u nG0[uE`H3:7rVʇD0 ;0s!T7$kH&* [{͕}WfvExQRJ:>lSBtHP06@*x+E*HȣpΈc=۰G1G^YKY$$p% T B3ՎS3dZ5ݟ Ii.0PN7qgxw7V|'{V>g:.l+蛝NH J8JuJ)JD@7uM_5x,bA`K6yXto eD$z_HqȽk`N⤣u Z gl"&xg';/Z\f@wL֗3Lק7?ic+a<>uù\o:Iw`%콚ډ1Fy<<õМxLVN&wYv -€D#'1ЀͅHsޅs <LcMi!Sϋ΀*{'aeV9od)Ŝ5R BLTk|Du1 ^d%UDx -#|~;9H}17I Ddנ*A},/~z57$Y0C㰋=#"n˔񲋼(N\!Y#lB9tu_̈ RSYX7zT#ScަH㔨UpA'BMG6+eK}#bV@lDqfAPϼ݀эy\;1JCҐݡ|iݐ%3؟;z9,/"DKʹy?` WA|,ʑ 5QWקѹþRĕBxHDm%f#2ҐoE3[5gî۟ECDϏԻI!t>RXuuLm/،~.ZLے1 1 l{㩙 ytN)$(lR<-̈+rK虎 dӈGu>f׵J!& K:ővŻ?]d c5o4%2c !}'?<7^bUU [sW-EB䥰OEȷ94"=du 4;RW݆玄/dXkNQd%!n$6ThZ:M xv \>iw'En_ɭ Rs}3h _ڼгN90b+Ց#]wfhf8SbH `-J Zȱ>`̡ ] |0/pAA,Q~Z[I^wܝN-U/'6'/ x~ `mtB Hݥ;p >䚥;}`>endstream endobj 433 0 obj 2531 endobj 436 0 obj <> stream xuVKo6W{ MRԫ@E@K@阅$jE:!%فm2y3$#[HYODhI8aᄳdLҔqR hzq{d2eYy4rUD;-T QK[B;ڎ-嶪N8eu|+xdTbjP#mUt;T<+2Nw/c) |VE~NhgUiVi^}n!ݡ@k}j29Ce_q*i#vAc_H!.H@DjsGEޓtՃ6m SSjg=T;+]u׬j{Aѱ>kñ D=" %W Џsz;qE> stream xeN1 E /aA=yLEX5N3*}4LD&' .:Hp}G(ִmiEa.n2ԐF:hX|E|W#*u7lqh$6:d6qW=d~4EGL*Qtr`sO7 1:kD ,rT1,JOMQl,r^3YfFHq/C1iendstream endobj 441 0 obj 235 endobj 444 0 obj <> stream xڕYn}h. 6Iiyb؆$@6083rLrߧ*^dfԧN]/wPN HJI<Z0i݈ӭ84YY$yּ ݢu {زb",Oy*nuV|9iHj&Kt݌R-GmP47 tjZ%2=BuR;ZF/EygR1cried`ޘL p,bC#cRlb: .[k#{S+tG zŖWeHB/~n/ֺj 0@NsZI-I!\Qwߘ\̤/މ/g7NIە`H;xӢA2yץ$/ m05=d~=PK}.7<"r8+mn&H06l~ЖѹZS *9=s THl 8A7ȉZ\gb[rY/~<;A]e)xZ ّ㝨nņ0h'dT-xo;jEPRp:, 8&)B3lW4q9tPp/lMNZϧZB/Dh yqt> ZZD~te,bCa1Q~䄍UmXT!ϙ`c f}DB;sрݶ(p}Ša{i]9A@~@ϻXg'> stream xڕYߏ6~_AYH)prׇ^ (YE\I!%(M@!3o~8<#MD&?n~o~WLbxISJTSyKr(Cۑ\էAQ˞ )i]8e^c(jRy؞*ϟH> ]^*nr`Pm8惻` %%:U4ͼ# bh7D2&l~" (ꉱJJR,Ji he {`y<\@c<4)$?n"%B,䖼ˮG8)T-$F;i"88-IgIB &O!b9|e!l1nOO/:h5bm;FT~@m C-sj,{"z3"s䂉Ir{0zِs:&%%Vva39kޫ&u~;Pa?d4X5\Eغ)d@RaM-cG>Ϙwg m5W#,e60䷑eb3cMp\M,`f%˒8GQ>w\&lycl4nHZ 8 _5p*2+ * ) nz weK2'2O ҃^ECw)mwC%Ù^]YtE^$K8gz%1x1d~zybSY9 Ϗz(2SڒCcLQ잋ij\^|KǕhg@:HnOhBUm3Ҏ$lE? [jiZ(%?uUTC >$6X丈0XC\ }k rCu }s#9D:/s73"A&If[G\j Q#4 ֞~Fpf);sF [`(I yo$ ¸ouFpYa0̡5mcU w([ڂxb_]zNm 6w6DO٠;" B 2 [ı fϬlԲ@U_2 &Aش@Gcx&[$+܄]ЙyQA<#M~ TٵWZ5 7 r7I]횟蒰 Zj]m~-M]1.F Xrj<(8K^N-A9 gðxАtxho"=K`8`(\B͔ kӜ@IȜRI6ה~$Z Y 9 t\6fKfw$–u>yΚ+Bf7N\yu㮸/_!^F:..7.C`«lܲh g켷`Eg*FBIZб sNInqw-^q/UF<܆9)w]{Η!@0\Q@ 2W`g[ä }ڈHAhcG?K;PIsa@Tp_>y ?#.gs+ a^7_-d!UKRoH-γԛ$Ya;Pdb>E^]ڋwkLc!q0U[ ;ܦB oR8rbb^b&2q1<"MO11:8@/ <^@h0^|63`GYx[03C77&20‡;.GuY[?+Ƕt5C8 G\^㤟31zz|7=o/wu"Eq4E'†~/[ĻWP)e6tzRameFwbAF/[0?O7}qu?mσbStNl.)&LET9jܑzkpnnxZ#ିl  )JdHk endstream endobj 452 0 obj 2327 endobj 456 0 obj <> stream xڥY[o~_zU}KH` A iV9Ԍ搒&E6#yx.߹XJ^}wdO+LDHޯn,,٦uE`M͡/zP#A_  O*n^-T^z9E>p6la Q'E_\iQwb$×H$ zN1P)nHx9,+Ns!Xi bGI)8?Iipm$gFK%qro1jX+z뎡ƺiEUу[\#F*&DҒBPMӶ;4h@cͱ*Z/6vl$W ^ܦu>$}F"V8c#xˣcmd!Dhl!4 c)*cƊk5&9rם%4 90Z uWnv"൒AˁtʞU:WM&a/EفD΍Pd=xصuߎG$فxǚ]1j)6b4X%$AP\#3i@G)6w轞u/SwW& Ɛ򷗢:,pO-Ooc?VB&g9Q{RzT eEz>AM A(]HRos1ft,SSB;B^hARhQ& ٫bK4<-y *H^r \n M=&EEKwO*i Nt6AM* )*,cxhHu6{oX`hiQ4!P}p( 6OĨ,ⱀd[P5[h 2AЦPRwt9 lV-,ZtBˣ2zQ/>z!PWf,~@2PX1ïsZPʑ}KSi:b: ~rEa2hBzãq (i(xapcC+XAmLmNPz`r6$>F30A ь{S舄Hcṛ\#c[x}AzjTQ U}vm_ EHlKRqU]vxuGPKKKL=)C4p/c)=^3}=͗X'JpX`p3lՐ΃s,u[<,>|8Eɡy̱|6ze|߾|_\MhT\E eiN/eԾC ((ڲx/9bC%( W-e5 ǽJNMӱm!*i 'G>A\2)8V-2e ]2 TunUAp"i)US>ͽs,e8@A}谆SE=Cr@dӝz!A%=A΋$cstQ1Gz]#P}=[JE!djeۨD^&\79se5PF`&aSwTlWxZS$iZGH&=:QS4;fo< XqIu˽_^LedusDV9hB'GSa!r-\:<5mlR)f{*`PY40c؅BM\.VaoRfZVU5.sȪk>[bd??54GP`f[t rpiUHOӑOz )Iey?Ib$tX\vD]e{=5,=46fkM1: k;[˹əM҃8:3z7!L%Vz[aw&첦o^ea 30)59 _ӹ˛RN;T%TvX )E2(y}+4ErE{Ѫ?LF_˚凢Vj/˘ОL^1h#I@oc77/M%. 2{ jHC~nU˲^04ǢB$Bfr՘?,@E|.W:xL5E^t չ{ÃJSʣ+LVZ^q9n`oM)Tۭ\PKN^_=/yޝrV~4ۢG7NervG /`x> stream xڵYm _[`dIa;fQmQ82qױ3s_B:v/b'~DRl &of, fDls\}ZjoTIHbeղmԲbM{[2amhکd[v~ʀ8v`&I drMi{^ }lYun<;7,OE  W,-{'i!mh|Naֲ4lg!ib'}0$3Y[*Ky99-vnއcH"=t;c?j>3xP4ZFchҡ J\`>/l 0+VSk8:fބ$r8U4;hg=cW56͋.SWĝMVGlSg{8Ѯd|`\4|?7\IWy_( 1v8l\<~wkG6rp8L7hŗrDG($7r-< )%Ӆ&D#gG0VɼykY6w.V1Ou8;P&</NKpWI$cbTB@KJOmH)1ۥXq4;]I8QFQ""2=ӿ g *o5zHx:sGk;1zPmiXl Jr)0 `'bn~@y>l H.|0`o(_&)jذ"Kc-$ 虠]x:9.y{`B,p'jNCc(e[` ȷb5g\D|0P3 d;# *(@A"mǵ>ϠvcŃ OEhw*)7-5UXU v| ^hUBpj(A$ߨT"o\lf#Q]$O(Gvj^f[ ĥQ4c)ɓȋt )!=x"s4U-kڇ0>^7Oz ̫mO9 o>?5HýSA''ráÎug#Y0`E0b˶Q &z\\E/gDM{+ c!@[xO@4Xb}a6ů|#n&5eE ck×}!_ȩ/0GYYL_F&q!U ^>2`!\nA!<_rmxh!2fiePxTa7D/Ẅ́k$QvWlI g7-o<2hFml ut6S΍A :8_05\ P@{,D[(0pS=1 {@.h'1cO7̷ޅ$=2 D2N,L]f"?N3Z`WN&BҔO}vi3jo , O?TaP=;pDS)x#毋T-Ř~o7,[}Fk\/R!n͜~ G Wko(5^7430 /Wh] 1Mu5p Lz%`A ܵ]ڦ۴YOh0iM8TKNvc>1&ޛYsctZxi_SWlr(14`˃F ϽihK"(%oF|gǕ_+.# {{ ^eb q|)FoӋVE^W-'+.%{m}PGg@<1| 5?X Հendstream endobj 468 0 obj 2097 endobj 471 0 obj <> stream xڝXn6}߯X oHSh&٠Pvi[VHZ'PF8gÙ1??[F ' qYBbX*?nx2r~H2!دV7-9PugbPM° tx:IYۼ*ם S uB Fo^ס-S5jCrN-fBtbR )ON*E U) %ֺ.ILSǩ"RNY=+!(sJ@VǬ>guHc:UjXnڞ|w36|)\*Po }/" $\U`<7Rz2p=@aS~N@krwSMɩ56 apj,;˫:E@1OeP15l! `WD;GY:zw>/$4ևiǐ N~QxZ Ӂ)+ MQ,WX{9Cō'qP/poj4z %% $k˫8}Ӎ9;EPpUB*^cmS^!n_v=Y-RX@ ŋ3˨=2Ǻ v(hza R@5)6d-bE֡>OO@2V E"#:Ո:K[d2xhGDc̍s%>f\oyHjy/22lH݆nldPU{0Z֢*(և׋o%^]uݒ\xky YՉ3 a³g@4=u԰V{o+#Nj}k8<^%BloqYM'zꟀxr O."cmdpx H5P~>5>{U]%U}Z{.KۜyqGcDBbFc:M1#Cnwuvx iBi7WDƯMGQOc C6oV'F-A_bEA)+TcELe|ؤf^y /u?mMС Kb̓; 3Ӻxz5nCSv.9٨.ŏ+rDԘט1B?8yb>.g#Rg Q ".4)*I%~VA!O@N@`P?G #0pu_-͏qb25bK`3|w߯ *'80b%8ٯ718>Gty3x ]^ K<it?,ĕmR;:qj Awlw|qendstream endobj 472 0 obj 1631 endobj 475 0 obj <> stream xڽY[o~ׯX/'goȃsH&Ї"X"R/EvvPm^Wm Wqf`RJ2I&ED9>(q3m|ʺBZp)Sg6 W;YG>~cxUٶc Q%D&DzlNOAYc q[W@1\{vj m^n~ypHFD>XD2"eyӱu~i¶XI Ϣt$4&BhH@džZ*#͵0!ُ;H"cv;Gg 8: ?@YO꜉b}:#Й v{L%Yɞ!輅ގk+0P:VdAQGXbƎ8ш˄82U>+I $I'^qD GrzY@,(b.DrDd^գ)i0sb`jr $rk= 9ۃ^-)B]KO%Q%/h0uc"eLzx:iQQOcu]rF]S}aPR Lm>7ωm/:0K ˝SSnpjmQ^^tz'x2yj si p94y ]$״ZuVW~up!F%:)z*ӕw(fs౳G%~"uUXߦ@G6TAg<3ӗoO8f`HD-|f+\]NPbB̋>w.?/!u0A CθKK2tf ^&cz^䝝Wy] V`Z q]PJy&S0J*+Sehk/&!i;[lIJ6n^(y84t^ YL 1gWv-1tr|S7|unb|Ѷ+X2S9\Bk@/VN^9Jnpt9C/G 'P8η[\L.oB´\ѭ%.o|o`;-.לȖøGdutц&@{Ĉ4sCWICrn9rp|ߣ+zTB7n *P#thmw 2 z_{-V'Su= %P\h\2{vq~wΗA8ԕsҌ7:,өqf([;+{[˻@].1#DL5y VqlGl&3"v7~WO[+O\t_JH8Lo >9y귛^[Hg{C10%3"pd*ǪpWC;J34m4 `{Z>Y Ba3@[K8W9e|Yw7d"0O9d6QhņOr_5e䶆}PG}!8Z}|-<_k\B4_VuIǐO)ψәYPKendstream endobj 476 0 obj 2352 endobj 481 0 obj <> stream xڥZɎ6WLԈ6ͳaO |Rꔭ%d10Ȫ|$/Ȓxy{K$~xy?I IB%")0/צMWhyV|aЇOD"=EwENq|OKBni)ܩ"1k_EJ0ц$Y]\މK sZgkyXx-A `)Lk[YG#rqkGiiV0nw+ꊖzGn!_։T|{2Uz&2x&ڹG{_D B̯E۵VTd[ ĩh򬫛w ( { 8&OOXƍ /g6,yǫ )BOɔ%v:{Chݸ lNXJْÕԔQ\892n8֩X{wϛQU.۱Ϳ(&{HW`V{lĘurV'QUm%Xɔ-PDZ7tjib/m D|ڥ Im|p"OlW&6ovS2y*kgdb{+vAeg>$# )yJ*H1?^$,EGc!.PjN3 P[?'ߍyuDkMnoe罔 gQ7;SҋU8;b*KIB+X{1{ N9 |//W_19Gl9{ Rg6o7{Bd wW`` V7F瀯j,&$O>j*[~",ͲpKD#vQf:IxB,wVkHY X;;mފ6֭T)?HIO՚ȥe8iBs E@H+7FA.tjJ%]g"MzyHC8%&Y4^Ttp1\PLIxR9ݨ^ U=yHOpĎY#S&؉CaFrZ0 Nok?0ĆZ)h3bh]D#1]nc^Ӷߒs БKGqs7[e€G=vh}ޠ-O?<v1yWg qp[ѝŭr@ʗZ_:LE<֊(Y ߢ  "Fc\7H86N|{>4FwUCY MkGVܪ}7 7p\~?Pv3]We[o@F˚%B1-ow#[a%W U54^ iؘ_nՐ6DKq-\ TRn-uJ`FeP|vtAOIO~@4;'n{*-D#$+.윟neu5mҲKөX4o $9D݀R2`#>h400rfLw5*hϢe WP^;SfS_Zu0l WÄƑ\jch*2T S=JjHoE#-lMA4ZJ=\xY??_":kک'Z@[لC6.b[#ħۓ']k/hB?}Yv .ZcRӺ]xninYR#fQ=U!p{o ͡{ rtvܱ4^ ۤ]Ȇ].Os:ڦ $Zև%$p7[h @qڛҦۖPat_'R|8tfdMzy]UpQs^}fπyjwXWcTkEW*/swk+_yI-Uc{-g@"W\ĒϺ)4{OFnwLަr-Hэ!)f8Img\o@34whje@5u|q߿E2Hoxّt;*pq<7F˄hG`aˍ[{!ϽK2Ɵc&vA}kNj*tpΒ_.}U_t~%VqOԦn?C͐s^ϤqI5+(cp8'r˳;GtB?0 :`qs`&IKVm5C@m5zDN|P adK_um <4]hɽqH0l5/i#1}8e ݥ_,%OWY0}0`aaQ~H_OcӍPWaߩd,4z6ܫ`??}y"2>D ?1<#1_Eٯcendstream endobj 482 0 obj 2791 endobj 488 0 obj <> stream xڵYK۸W8[M6V*$l cmnYrMF믻1 mc;Xacă?𐓈1FX^7IuoTU,-IV3i*W *_3Y,ﲄLI :7)Kh">LaFFU&IҪFR3.VAD(WV-))T&;hР.Zމ'-qIZNB>V |Xlq (y`;j h&*eEҍI﨓Te+= gҖұc4w5m' iqkd]4\<}GY:4%?Hrl)؄&a7z6L4Iu©s}`~(RH8&1 |{=٬/ .'(MzJ5dGWr@2ވi׾0T^ӑeEګ}FF{ᢱ SV=۲{4184RY*z3Qd[-ZXߺ*Vɾy-]mc wj u5ϵ_xJ.i.naiBιcR/e1ηR]2jj#+y#,l2՝|FsQxtuӺ"tS˴ =l,j(ަ(69Z>!i_XYidxo ` t:YlT5 Yz2%߁JQ ?7!q+xyP8s!q bdb$,o@=%8>#Oo˪~|(މ?f ǞX*6ȗG4p` y?>|Phb0v4UL< pF&x60%v\-nOZ̬QSv3-(O9D7y٨.B 8l#(}[R)~lgǤ5&e[WY:5ًL81~FB 9dpTQϰYzm}zL5mЩ2ZU&tl mͺX-FvcVr;3/h3E@+>gM"ĵڴf0-z\6G.g#|Z5La#)-6ڌS;ߡNjut5 <P$i 3!˳<]#BkDA.t`4^O`8XZ.v"+Գ|ufZ)~LФU6z`\/,֊.oRh7U]~HgUf&O yz%"NcWǛn6l:tx{L7VLak" (ΉL⑳ʾqq7YX<͑gUCլ0/-,ۏt=4jͭ9L^eRM]bEl@+0weG0u[kgabuؚ2[Y%БH#ؠn4jaly=ACa#g9j@f@kc;nv#_ђ(Vzf-#lwPuoK(8҄R+߫ʹl޽m=_5ݲۢC C70M, P 5ٕ~n\7WqdŮMR2>$=c/h]Q@P bwgHp2>Q>2)y!C<ҡ#eCfw{!^տۚt~wkdAC4>h#1OÚ]۬QVendstream endobj 489 0 obj 2248 endobj 494 0 obj <> stream xڵY]۸} Y?ǢEbb6k+K$o_CJgl-P$1gΜ#jϫŇPZ %"QBEH\Ɗ~^K~a-CuٮNT4 \#>|4@<5u߻q/7 ^AGYB GJҷźDYov_}oZld*2L2ScwmYg# }ӎKXձLV_i&c6I[Q7h6N&߈Jb!DwprsE|n{Q)CUvpr _7uTN zV#k@㗑Y.ebNÆ=#B輧>:+6ٹZZ|+L\KXŸiEҬ4Y09d %ϕF2N(*r9ͽ:wبw|%z86X:eRjZ.]ܖ=XUb# էjAǏmܸ& rN3)ub_we햞޼ {S{S1!:929"L٢U2w߅رT2Avd3  -Fg*Z!l wN$[Lw#.#Y;5aEOy-[ei@ߦ-k w !z$~FfVQ\Be P,v߽2dnC1{ېR:QysaJW te7:uLAk֟SٔwSM/(T]jS;:*eLD3{WhL/{^T4lk[-<(xzrmv];̾ti{bcoaWO4"Am'o4*="_`y\E_ߋH[_,1 TPV֚WCiȘOG]L "褪QV:vmq ܤSYDCaSsjS`Ħ}P|;)XkU]&Qii\R CNjʈ{MW,'swE+x6h 8w!"PE,IHA?Լ$Rg{3;KQJMwuϯND BS@іCETЩ{?i\inn^|A]\ͷ 5zq I\aL`Vg`$8"\/LT_G #?[.C z}:[> stream xڕXYo6~[ %=vmES,ʒWG u$bf83<٤GzYV$"݊8,"!TdsX]|efoon~~rQK\q+iG}VSCK,hȃJS.2.7֦"YC}[EdIH )wJhkA6LڔUfjސ:9+CҐ&mmؽ{s&,x*R4r"(& 9e}'S>Lxm6 BR&=}{qguJ֌` x+pdE Z1Rf*43pj5{"[s%EҕHڼ${S,ɊTͣZxwL#a7 i5UYѠÏI%ۤIf#Li5ͱT _ԋ 0`@3fkt:R* gb=6WrL=iJHfʀG=Y?}x_1C%;!ќ_98NS]!a\p_)tc|J {Ao:nAEl+Ǝ|-c$jቀ~b` c5ȗn)<<0ʶQhit+Tl}Srai*"/ܾ?+ p'6Z a ?^UtvJ8j粁àAp$ϦWoGDQ Ifzv+{ r&3EAD9L!8fZJZFsdҙβ`[df@B NYhި H:b{k<zqtWezt UF_:c?ثR.f6i|$;p="/7#5Wp$a}q|_% Ƶe~'EMa#C<<:;v>+Nà~|CwOOpZ}_?$2w6m|B1V!bٯ~'1cendstream endobj 501 0 obj 1805 endobj 505 0 obj <> stream xeAO0 >`'N]7N&E⌦m`E8mڡ({0]0,`Њa#ad(`Evj7_^zK! 9yJ"|`1㺁ܼL?H%v*89x=G^]+rLbXݚ?)&GY'0|vz^~^endstream endobj 506 0 obj 223 endobj 509 0 obj <> stream xڭXێ6}W-b͈$@E 4hk%DΐvMfs;gH#sF6uD#.ȦWۈ 7W?1"[1_1dsZ497_HiReݵ8 )+Ի;b@BMKj㥬ߤ%yԭyђn}E/,#AEg^[ęJ('QG_V;Rw< CQõD A1d0aW-{kYZQ' bsMSH j3.Cx1  MN*Ƃ0w䮆mqpGs}n2uUa:BNSϞƬ$0||wl_ W7 @?c;sX7K RJAiv^ v:7[\*nqsC??>5B D))ɀ|Ɍf=PyNt,@{h[@"BTpx<=[n(c ^υ'ټ]ٖ3=ܝ ^Duk# =fYĨf}Swɀ{ݛF#Y/cSk[ d2dC8 A\>M뺿 WB뗺)`^?<ȘC"X˷$؇^7gl¼yB\o5~Yxc\KC^*(z Hx|GF qEǸb4{G+uCcx?~yo/}OX =%~b'?ы*4\{tO[ boendstream endobj 510 0 obj 1766 endobj 513 0 obj <> stream xڕYo8~_AeS aE;CZwŻ Pd֝ly%9vJ8|MQU!9?f : >W> &+?iㄭwԆ[F(ϭ7Egv5u2XL^eCݯӯ̆vkO^)}Bo2 $-Ɖ`gAןLy$}Ӵ1YoMÞz4ihXa}jv(4[*)%OcSƪzc AJP$yvmjfc`|[M `r{M5 ;DXWDX.jF%!Zm.JC5txwH$؟>/)E!U' < ^@^̘#1@%`{S49:0ym -؞0N!,C 8Qp( OA,dGXCBԈ>иEM>|Q=mH@sȷ$IMt=t 9=IN(㡾$.o<`>agRb-2BxK'Q@o]Wlc/C:-{XBQ%QL_< 'bfo x*֎q3fݖɞRwvɵ!kOx.v (l@q(MVcv8-U mhS"/P8hWIttJh$%&=8_[Mu3u qgRlل ("%kw25aЉ$anS/GLߢ 9ymb%RV+;@K[/@ d+|;_"5ҽ4Ŭs05if]#^ 7p'6r[p(JBD*;_e5zw`Of6#_z`2+CU$D x*7܉"HJ:&MF!Oixee0& {fmU0jecm*" œ$9H :LSCX ;5AC|s;A\ 9ZaWd9 p R4dpM)LBxSEM %4'Lr1aqP )EϏc!v0 J,Qثɩ O*IBHmy0҅,;B?siw_q`^M@"&qL wz@ |2vмz/y_cD0 $tJ'StBUC3YaR]^3Vʡޞ ;E CU5o'4mL л^^Vu}[\3ÊpO*ppN%OzC) З+8+]zS)I?% Ne"Dr 7%[%nAKb6#Y7c٬I !bg>$@bCv=u8ksqXQtx"w]d A-&\,I_iO߹[0^qlxE V19l#b_r57o\1PםUcZ*K=Ibɬyi l83['\}ҷhw۴!F(ֳ3FG"N ?5(zMAS]f@*{ *i|؝!Oߦ; ˌw]}~^A;*}f?m*(@1@q  n#ߘɫzzq a+>Os*'8> (qz~9F0 T<V)wڭ؍PP-Y[uY5y c/sGw셩&T $0',9QQ1$x(Ow0<D/,?W(!> stream xڥZ[ۺ~ l"Q[l=mK@kCYo}Ds$y H [3ù7t"*ELOlMtWv3# >l#C-'C,4gUZ4 I<֮mAJg-64UwgtwhBcSk\k#)=f[p?p~rU8I6Y P7Ǣ/Fa;ޯ|t8`g}X\磎Vd wdPIx݉,dm!NMwĽV)vHb8,$ ͦ9rI)y d=/nN׼)8L,zH})o-/m}93ƛrp%lcm\p 9 圣410Ct_8xqgI!FCY ,Űg:34uǀ,CpM6@ȏgs#`*D y\`_}J#m25C*gWΐ1v6?ڏɰ@l@F*$;4+fhHC -l Ԭ-<DZukwY@r"..'!%}R^l˜kBV:T o3@%rU{Bxf&RraM` 7mưs#xzЗ2 r 8y>_]8-Ż[Zߍnh9`06qMGLGL`z{&{> stream xڥXY6 ~_n*ɒ(i_ZK֣q]{חIٞdA"$~1';>vƻ$$qYHΩJI{zs4YvTiĦn^şRc^C*1794GCj}2gGƘ{ϕ5y<[ڽ{2yȧe&ҎTqĔ 讛΀PebB E#WYg֤2e'is 똂`da%G).% "L\W$k\AX*{5ڜG,CW]=*I"t(2t |[Iew3H}Q1xmЍ{7g_d Im: ꢭKB(Te>kS鈍\P'<'m]f:WV8u܄~nH(6hؿYq3DJ dSl!J!Wd1fЛ/8&yjs/Xs7%RkQJ^G60GoKZ☆^PٞSFc]jLӇ}2iy10kJxJduEZ?s2[H76>e ^Tx.H]MR@F/>En?ic4?\L)1v#t_Tr| K_~ͪu7B%VS\W ,o_JhO0u̼Kp2ǖ5se|KGSMư/mtշ1PS -ͩ-LsEbBBqVXbR`5A' N6%4*(Frp;x$GCh+ D<+/7U>@ka(I"a8^r<1;WE{8vY}%=~qlzf8lπ{;&>\wKoJn> stream xڝY[o~K3\t;Hݜ( yPV+K^I^Rסd'nPldH!?~3qp6V/ 90_l[<}rq(-3Ȣ|ynf° 1)m9x8N%Om3%^7xfq {1|×V?<}ܕb￙m9;ޞχ羑Q|7.X }NlC`Vo$Fp-g'iWsYnnac޳6Mbs[}TFIXVuWF(On47 ӹ/ Gx' &tk"$o`ڽnFLqdNk<9,CA sTG2հmy\(olSK࿿7p&<c |-mVEi*,M^bKİvbԔQoi\mGirL/5KLJu=CVtZ5isqjB`W0+&v vC05%/hu[TKbd'"5kaN[Xì7e=C\ >/+NlW$ U8qg m[f'~5V}}v1hߛpܐ~#EotRt I{y C+&軪9_(tfi}‘ (M#"(r'жMjX~(\y vGpΣY4{!җ)ar-S~4 a|Y"/nuq=veն8dI?YCm[`>qe%77O<&pm7XY ^ں&dŔ-qT湶m-CYB Ka(m~ !O@7F{iikҵgy9y/]\=叔8/]Xε_th0*M\7@BL5 t]">^QZɀ3M D`%.!8 ?\b@ut c)NUGy7K. Gp7&PX)BsWi Oچʆ#,1J;JbrSFVސƴToEG,ilTM8uw-E:gJu]|ϒT}G!h͆dy lԔ\iOr_`l QS 6G >$d'Q  }w S.r 3'Z0-IS0+O NAqŒ )ESdes9w%Y7依pR0 E:Q<"=le>Y.w~DL^iZrW=e_mg>pcZ_"k59&w+-g}+Dz>CdէąJ1gLGﮟ6|*orxPZ׶/.[Ke;l=C.s7l?L1Ըzm  PqUx||jhf82Y5їtl}H<,2F";53q!m̯ bN^u?A[y؁:j`Ә}νX*Dp;m SGLҒl wHyE2 f?;o&ctEQwץ13neh&֟| ʼ=C31ok@p|G%^BjͶ{B ;); ~VLi4@᥮=v'Z~×m?0q@ `U]aUN.J@t5 /ٽ%z4c6endstream endobj 528 0 obj 2274 endobj 533 0 obj <> stream xڽW[O8~_qTi%*u\$v% -R[h'}@Ba@vs$Sh'[ |nΜ0v)WB1c# I^\?J:"l2Yոo`^ᝂ3JiisOg7څfnp*k Y|sW.S Bin⪌hHj_銴2=:I(A(ER:ۋc8"tK#RaV2a#IFG ”K5)6UdSq굉0Ο6yCDx(MCXFi<}-aǩɓ$4{/#JdfH"W7 !dDǐO KGpxt ~ä ,oYg._tcJ[gR92ڏSo:v#'3Uctƨ!~;{1N/qçT*׺ x&:79>DsNR}Ǚ$ eOo_'OH/S\:4(6 zNQN?,,!FHo7E>].v9Ƶ{(ݕW?v,me4 @/ MTRDbc9`UdMaR$pJ(mα1A gSQxUú(1!Zo0Cκb# y&<O#Ɩ;T?P&I+'9"(f4-4R$P6]1Nnv`SGľ1MM&L> stream xڝYܶqIQ)qQAx˽U]m$=wzq(]r) r8/7T¶OmwS„dF&IsiNiJ?~x؝3j5ܛ RXxJt>X`V\h:Kֹ62<+daٱ1tI}Ii]m9sYs`LuTb un%&o;s=94-3u͜\w +\p4kXOW!Qhi-q\ݳCۜX{/d;dA^((A3ed=峌VUցj®ג{ȋxݠ:OyN9$%=M9n4SV,Oi82 bRJ󁒱5WLUx7~onlDdgL {4oY@.3^1U۹onR!yjOcrQyr"\FJlC!ɳ#}D;쿂ODm_^Vp@'`.;ϟLԑSBBSJ^7}PvNU,;5}A=j.|$_d(d!EZ"P0̧xKHaH; ŊԏSẺ WT(i@DE?FJ ҏY}-x;&-J>"쭃 [t,Tv-TiS0+R~h녎]e@WŅTۡGud^{X^ ٲVJݱ/vk]AP"r)\R7!H_#87W$0GLsmuO UAC-hx+)vm\ "stݙj?}.ULA* yAM]^8Lҭtb}>Gx(CdfzmQD0艡 }ɔGgL:j.'O1 1egB"ڜZJROea 19B"ۦ4Z|}>\x(Vr|NO>w(s5&St{L[ ?/{U:f.kq9zhV8:ZszlS`. Fuka ΂ԛ1<!˂ލ aDʵf˞#yY@/m+%҉uzrLO# ~z޻hXjsͩ/&mD"oA7n%jA/gqq/v^mendstream endobj 538 0 obj 2482 endobj 544 0 obj <> stream xڭZm _1/ެE#h&k (p@kl~}IɖHx8Bȁؾn㏁PZl% bbHe[6D 5pJKpX&1[C6oPG\t.F҉ 5M+r7^|Ziiؤ/.Bd)/۴ͪ5P6)U/ɂO쓯4ߦ5E pe\=z۰:UTȩѹ)˧i%߈"=F ]Hw A.6`ag6?[ug8tGI$c8yWBiCg9V|/ʪiT.ԸDZQշ3&~ &PT<\SwPw $UiQ1Yo~䱯WcnO~wT\Cjs鐕t|yÐTd1EU;$Sd{uCR]CL#$]3("~cQ(+##vi)=^BE/.5%aKTtPyM+S]|fKoC/ޘjP t6}k_šo9]ƗFm0DW1k ( 5s1=جԚn,k|ZE&X%5sNi 9io>C5gy@օlAdX5I[,Iտ\徇S߶u1mI8NΏ@HF!xmfc*Cۻl%c-Q627OeUW;4m1߆.gV2P?0C}]0_0uI~-AR䏱8-tCb3t{@8` 8D,Oa<P&+3 4=Ksb˾0)H$aZ"%y0W,dPvg,_a HK_I'`=kˡZ' 4z0 Ox`f5tvaw ,AD ԰L-^Q;r޸H2C"-+4b(=Dơj:pH LGv(ID_=G~-*Ƈ6:y#}ե;P(v54ΰ䁁n;^9)^˵[yuV bZ3l!azxv[tsL"*M%Rhj sʊMwj չIC@b*|?-6&]$2C&ʷ2*XW1bm)9r#sD@6Q&(2EDQL$V2DщwΑh,5}J4^yVia[7_)3}#HT谕b [;(~kϫ鮑`bh@?Qĕ+H㹩jYx ^0e$n4Y:ޫ&⋪OGO/`F&қo&S&:ʈJ-Tv3^3B ʣ}^m$ct."zGC%k+5SSчDv1FfuVgiFݤajsD~٫&')XBGMuy1 {>^}m@N:PJEt11]n\Kk5 k? L188dʓmtqwͩ*ۼHHlAF;_a *tI@D.\LAjÒˡ7nM }{ZA[(wGZۦ@ҀWA7RTޛΙ7]8҉E[*_'$i>Hj'+[ D|iSU* ; d`e|Dw]ЌW=] ȳ2#34ȫt?TkV_Takuܵ'sחs_LqМ:juƼz<-aBW챳M(r)QmzW ,;ԽE4xLX e5*86cLNury``>Mo֮4с] HڜOӀӓ_!@dzvDv桧Ot~γ T;@ ~j6uL_ nkfC>a[x򾳺o>.b.-T34 '0t=kާ߶v >*B+6&|#H /xW4cP"H:rg֙ beaxRؾˇ1 D6^W@UUd/30 Z1 EAF )Mz/q> stream xڭYYܸ~_Gኇm8eGVWR{<.Zj{`X>]09A;O0$,G1ۗw}7v0t(ږ`ug.M}Mߞr2n}azUHmKM@iăTl QASM-; Yخ⁎}/Mٶ\]T=.ôxDџpNnDW?Q ñ. 9W{ͫJeQv@값#R;Mc˺B GbwI.Lwf]{ylwjLəoJH"{$PsIeEHNiXW9?}PkNqC۞7 JE\iJ_ok1e9',T"oު|a2tV?[G}'ZF@4\Eߙ. <%zduw=<8Dg:REB,BNTȼ%̋iKCt IqvSz-**yF KUHzUg5.jm̾퉠CNq #N> hz149t-{=p)E6#qnjAFS#RQc\t ̅RЯ:04&lT\E؝<٣I{Sip̔y/b^W3=M)?gȄv.S^ #{βkYC<)F Caׇ 5o];)+:{{oD=$S͍mfCN Pr DKQV_%S1Z 'RP=1a s8M@C=D!׻O0ޘ$a)jhNxu6xH"8eB?Z1ﱷfilA2VJ z1BBH>-}ܗMAdfWЏR((%z)ʼ82kI{!e Y Rpu-M&*ZR|E՗VTW ǡN͵BNp[UB %y)LF]{H"_pA˚mU94C7`2tmOWȆYdKL(:c9ƫĐa¡ۉmWS0k/caA7 (x(2Sa `8iZAWHAj#`W/:HF$ E#B!]^ *l"[x`7 4p9oi> 974h002&qUP l;S@رa{n/7NS"496yLeKW@\'1E O>01|ώ ?uguy݃D~Ml߀#TbMWzΡ֝,C sbyCn{Cw}Qed{*rI2C^BS?fDDd-aprf] Ć>omg;C7$Ӑ C"G#4#K p l+$r1l*"C棹 lhtњ|XWXoJ.g "`w!].?0ЋO@L >0~wG7YUBO&us:9<֒M_K8~,@&o׶~7S(Zua%?NQjg =b=#=Y[,endstream endobj 549 0 obj 2107 endobj 552 0 obj <> stream xڵX[4~_u}K B%(HUٌg'4o'=ɶ@QՕ3|.>߹8+F9߮Z=g ޮ8a4IXJȺZ=TSwFD{HȘQt=@ɡ3AͶ)5GiE}wI4aYU7mG]I u+y704y1Ĕ7z' W}܂&J~a۬ {3ϢT \ꀜh56`  aVD1S'H;Ϧ;=yշ&?lT2;ooӣki8!|c(b b(z\'cx0Tyl1udSt2{HM[ dK ] 9@1 PW UV[e7%ָE ߆wiRAuxn-YCMEkO yVv ~Itedy$*T:$$qUpC@QJS=&vrl HND'YqEYª<C0o'?0ćg|d<;}YŸ4\ca /?JD'e0HJ ӔwAh"F!.ِ$󼸌P/IEv$yr&IXHHq"$?EeFOfdM֙0,Fp z7OZmS:cM11ggR%dncP.0?~il""ₐA]0‡a|CDjbS$s@%ἁvCs8xUSwS~\tShMٚԹf ܘ: !ծ`~c&JD"FɰbZ{F ɩ6@K:A ɨ|7軪PB k_wA%lL8#/R.[^-_/]-m9`̣~c"߆D>vg=\$r_gmag;.BBh:Ԇ8Cs| -B. Z(%$,l0>v\+;aƛcQfpa}E6]Ǚ0YZsLCVsgਓPK_f:nlh=69Ʊ#7uxEiadMSJ3}0|)l7\5 D՗Ou;Mۛg NJ "9[~͛j6T ί‰r9b ;-Q/)wJ^IGQc0a*Ş&//8Go V C{r0~®R=ķ<^t}S"ôv1oQ`ջ*hE }^1}@LgĴgzMj7L-Eendstream endobj 553 0 obj 1914 endobj 556 0 obj <> stream xڝXm6/ҭ|藤MIu6Uz4C/_߱aò:ixG /60 D*4 hv!!طiIpп!g34yz0 Lu*Y}(u՟*HRp_޶<@!5බI@PF$t 4F𚸣 ԰;#\58p _F7d.H oWYW% L\S@CОNTiO^cV}9h¥첯l'=pxFy=a K?2W`B39:E5{F#2ydM.Ne_3*DmEė{rY~,R@kHtkXG`񥗽fe+`-sU~!cvKK]l W8uT`R׎=ݷ7zc9u#ԹZo$uo)&FR\ ӡc2}v&k^z*]S>{ܣAj0˩m'6TgHn MrkBco˨h_ĕ!> !ZsVܐݩ.QY4b{=^0p@ɖr͋įQd|nپsLz=o!/pL,TJ ggw3qrf8 "[I2lnV08g׉#<ýýpL~_ C#ڜ aack.Ӕ>vSd dçiq<~C@LcOw牐ئahH02,?/p89n?=,`&"L C]bn6*J|XX QbPEQvqZsN*-endstream endobj 557 0 obj 1899 endobj 561 0 obj <> stream xeOo0 >nevHHn=P)UKa@~9Rb?3[5xj0d12y4Srk_4s NikUwjܽ9}>>!Olxh!/dVR3#ep1|QZA."3cIcdb@lgJLFLxNj2\endstream endobj 562 0 obj 220 endobj 565 0 obj <> stream xڍZn6}WyYadg6 rNVRO=E]EI$Ub)Rq癸;_nu_~~$+)bK2JT??vSww@SmW{xگ/U"teRVr-Uzy%R6XFhDq„nQNؗ庹g*LFi&{n0pqn=d|zKCo# &bB>@Q9>4jF$ m񅡬Rqxw^EӔ Ygq{)>U[+gђ7g*PuE3Q "MՈ3B֭EX#/G]hO4'W=mțYXWLQc #"? R$yNI …vQcֺ,Z'FVy3.&2Lz;nK ޕ5btS]*.v' aHäRJ=ɷ+6Bl5&<MԞOrVC[mc[;\"Zh\MREI㜍5U=U M\UM'\ wUEe",d, ʓɫa?bvXK>'Dc ZeQyR N{Rݘ\:r5L9ڠƗpf;(Q+FgB;/ JP|.y)_k$鿆.#?G$c]Mv(lg+pF$k.ĩL0)MUɉS(es335M(LgvwR D9â Tې)׉덞9tǒyBi$Ͻ/ WIƗt1ɩ^$eGh\42) 'gmW2؂3c`qԓmr5 Y"6MREX!C|~-xG+3؎nbZ"QB;\QhU<ρK6-<:ֹl@¦ >ėTh[x&yCμ~ICEa}5q܇O`7c9ިdcki˥Ht3*&*8JAqJrI. 9b [< bJmQ?Ot\HJ3>()"& b[^TL|yg#EgcrjQ:)PkiZC]fR9A31e;6]lڑ~(>6^5.HmRC'SUn ZCCH%Ԡb%Â~ Y/b^`uAԽnMGV!5`aG/)3BZʝ136j'XbcTtň"$גw7nmSo _w7 tGǝi4t\Y=u?ɺ|,Nϯ$NKW253=~7#H4b!H:+p~{=relҍCF7Nΐ 40qa+d{/ kki k(0B݂BDv[EDŗk ft,,dt~>mi5>5z.bXn#CYu}ၞN; XSSgh@w_M0 ޹NN͏g>2Lrz˺?ؙg`L}V b0dOcEP}O)fq@,COh t҃6m{|>s6Ae>0ۭD76nmߎXI*2%=Zv'k1Gvl8 ơjiv|*o6)С4Sg{^;Zc|5{n .YӉL(1>Q O(IW?( ܷZeon.iNXu|b}A c6W=d@}{endstream endobj 566 0 obj 3268 endobj 572 0 obj <> stream xڍYmo8_A˦@JUIvq{^} Pl&A]IR/Ȗhis8<̐f46"OX3xp(4"k?6| F|>YM&j@dI̟&0ˉ$5\zrEOJnɇoϻ-weQ(=nYW$k}#w5 "IJ+K*[fiK)dDIBY.@YGK] A@ZizQ<~7!u!t~peF$5WoKm*dUu;}xXY@?L!tƛHv2A]u_+QYoxt{>bYiQzO{ e\⽏\q&Ců8+jl;%nfBS=ggO 1MF _G#☲&ڿΊNj/Iݖ-pmWRn!Ӻ.Rw5pJ!ĉֆ{͗E 1u~h 2 O< u$h˴]oHxJU]@5ٯM< Z2\ԙ 8HD|z)9HzA~P<8!p%' *yHǓ*yHWQ RrGEN0' ~t>KKHRhÁ1{Fg RT.ʆj$ 1I#*G UPg@iiɮv[ћbnDgmZֶ(\3BZ#4Y@”62/ڒOw5wv>ws]NSsUA- 7JCyG5y-!yyY=Rvz;{MBX5rMH&:TB. ntp "gI^TpąaTid. PH ̓.Oj%ͻܬGj0TOt,܄usl [ju9W~J\YHN\8͖DMpZ:gUS% , mjW R x&nh;rre"+(Fe_Y'6.PLpa0"~\QJ\4YdypwܞhEN+U W8$+Tf4bƒHҎY:AI!#?G' e6I5-t@/ Jc(gK+tK (| :HOHPP(R`DP%]o]$Gc% 5y&*ZYm`bI$|2OS,@*IЙzSۦiOz Ƒcϩ- D#6IU.w!U8wb*i=Áp>A2Q 2wsNl)ܾ=y"^ϗk ^2GCG Fr_<UT5Ѯh]\G#ED#.lC@b(\ކ סC%{@Hl%C铕 a #<0YK t(<ڐ|Ss4&بmoō*eWF}i44lwdН($6w_n <1dI0>4'}@ēP>` =ƄRG}hK]^rR* 7@U~P ~}ے Q}zE "߼^|9 F+= sY>TPbg.G7zR!"OxW#`˅J'vN].w H_>hq7n\?6ڸ觬 D/O kVuu6c@R [_ `l{̳U0C/4Y ǎuz۝ɢ$a+,[ȵjVo#;n~-oZS”47닿9G<-!$<M[ c`#&qDÈA[M |endstream endobj 573 0 obj 2309 endobj 577 0 obj <> stream xڵZm6_A&WQ*p("nq5ELʒ#ߐz1)[&F?<>LpB~\iAIaY1$yj>zA`~$̀ݽ@!ZKD9攡vuxQF5<⩌(sѾ+T()u\k]&Ro We̓VQ$zWI+@Rlq"xG꼮P\Y3ߔn|sss{f,X:g^릪67ߚwfԐ@(kv4uZu)"GDj0␺S9Z1-.{Te.L׭k.9;"Nn4;cLh\ Sn!<}rdCE?dqUjf)4>}eYfhH'RWTi\nj#Z + 9gֿ7 !oL0I̷>ڋF<2`t94$8@~fҞK8LJxl0s\D`AWv-s=U`X^vQ#Qk4t>>)J'&t3{5YA4t'/r1qm>VL,;Xނ>EL#/8de#ll:6N6EI" 42q=Ng z (2TD"ܧ=62$8_p9eU^([h(\˧Vȡʀɦשdc] ^q(۴ KzBe\M(T:qp\R(1 qBqedfu{pdZV`_^T(K6S͟y@5 g. Q^W'T7éذri y)` <NF+.)fi5:Fܛjʐ1ZkoѱCy_N0M_)c l)_RDAeRatiTؤ(mE( mHBcSvԨ5P£nŞ[!h Oud%,.c,\,GG zAWP|'DtDςr^mM94&36^ 4~?ST9Gʫ:ӗtmb)oq ydP ]o^FR Zq?E_S9}2VXPc:"2d¥?8]EIXwϪLK!bxNSpea[+] N*!}YhZ Y5H5E/7s墆zá^ Ĝg N%E%VxMQT\δ)6m=](ԙK>`]dJ o毐RXs]MalQh7K& >ۄ'NvDyrE zI﫟m6V]*'Yؕjhh?-7leӥT5ؤЄE.cۅ O\3.E0'U&`bV,>"d5+ χP i`@ fc6;9՜PHC' ζD_uhv£3V9?:Y(8u1{(yh||Jh#b#m|, \yzj8DaoIinH+ t{}+fsߨ8Me.j_˭5*`gߺp3H]s5.+mKskFzkWh{\̦TӅy@{ڔvXZJ7!@/π;ؗ*Դ ʼa IKؼ<(G$<}݇-jS׻o BM?UAU_]nݗ-EahTw]'}SzgHqH=^9=4^u;}+G0(LM~$nD0N0U$9y|+H}OS@I+AܺjA:<>=!jΗp{M!A_ PvnDP~:y|+s2!JFXwQ^3˂`!hXЪSv/)T?tmP$T%c_i°tFB(愳%Βc_t*]88^9lwzpؿ+J f5iH_.c 헍xPt$k5<:sC '̺OP֑֕]@[ϵv:Bp] :6 #HEƃ2ؙD э,~G9?IEendstream endobj 578 0 obj 2461 endobj 591 0 obj <> stream xڕZYs~篘ҋ*z9p)mvT jab-7tM$,gϯleEn7w7W7 X},?)a<۝aonBB'#dҾ_߫_3V)bҽ,+I%δ._dc=tͫamqP.ghuS :. 2ڰ>=QpUY˙{P#lBašGZ]7]ܢg\*ՍLx 4 u4C%k VpmOu*yU\7po=c:n-r)1_}7tsq8&5u%#{XU6K[(0[@?MVBfBôi(L&<#YxEb^bdEaQ:9#f>9/Uv`"/?K= P_9f o!hWsEBq A [ @ AAߗa˙$to`ol{z$luۊ4 SZ=l! !%~Q^ʀ;X(y*o#ecn8$fWP +=: Xh8RMC8 wgv:Tء>3v|jsr8 Y]umJxPKtD#-شK'0Ǵ W 64uo"YH1ြnKN..Pn8O$HAHv*`oFFڏ~('S晶!͑{ $"R6x#mzhI?]Y}L1/n*iayQ8ʏA)M9HI3(w;ȍ ܉iG H."R"xl<$d;%X#ewi"%:bΩ"ic /ptԴfߓ@:7U2Y ZU +xCT5;Y 'wiڬ:VZXSԺZ( R!*pzP>hz׍AheYW{q@'"{9 !a "G4Ll,[Z,-mt)XBjF̲-IfgC,2S_p7bٹX J;綂^l_mN΋Pn @5Hj,/ElS:K~8r 2y;@r(@puKM9kA^A. 5KVQ"m@۔`eɶ0si95e M\D=48AdP>1LhHs g7ި2dͪr|E'gey֫EvU{lʼqc t=M+VTSp1ׁpJ`o۟ľq…rΛAML}rtЏ%gSLeͣ]>]yod\#wY~'}c*3:&:aR-΂c'ġO> |џ7&Xl w#-KRr):H^mN sȜZcf}ҫzRPF Y4D@ՔIhN. iRo7Ou?EԷb6vdr·#%/Zz5R[x8LIۼ9٩5>}qvP6=D^+x\BcPx#RAI<2`=AdSK[Rkw20uM3)z0grm?^k|sƗˎaiˊaV|JJsl{t|* UŬ+7iCL}t UD{c߾+ɽ^~q#ӔC '!ٍvP+;β)sy)W8OBVCPh^ E A /7~Āߍ/^_\0乧).vkd~Ɉg"]?}E\_gWD ^)N0{}fcɏ̧.CY"j]g9+Q*Mt-˴VR٨vU"" 3~wz݂\ÿ^`P\|iaˀ5}M "vm{x{uu!C)^p@*> stream xڍYmoܸp`3Ik;Zԅ!h^3P/bHp8gFOT6}xڄAʒ^>U(PY6&`3 !Շ琅 Y-eq*jlԽ~F%<gwWU% CY [ݝ+;NyddS IDrτ"xE^4;eqJX&@2<jU %< kN.+\]vUuK]+H7$uTl"L$trƣxvXH-ش JP wGEA/,B $ E`wBvGk5{ҵnze]ߖSw'<<| X裮559;}=yCv#ґ.ٱmdbq!z.KR=BjIV> 3W>+.Y jt{]ۭ" "!m5>4%t וO5kAP23R:L_YծU)I6jy 'L%Z5#a&t R_ WQ蒝gƄy*!u8yÄ)X /d5~U0.ֆی;!caS!]w~)42[u/z0 %uL/dωyjb6.H]46~Ъ,r(FO]Iag- ^QJȡl=@Tt#Thj)?S(F.w ]D*[Q4FHCG%bfI#vA5^C'7ae-+ZMr1cre=GA#: TV+?UHJ@@MP,da9Y2AlFȸ %?A]5~Ή1v(#PBM޶ H* Z"Ko&nm6,.1n\\. pDTڴnnNuD)g>oPm]qhڼmŀKDCx>7$f93 ! >cKYBo-,1ǦY3&ޖWPCf.%$}6RS&RLΎ3͠71.+ BdQ.kj'PEjjP|!mК\Y\Jڴ X fZtʼK%P+rggޟfԍx؊a>#8vfܾ#WXONWlWӰODtd!o:,{rp 3&}=v۔͸Cf3mbt= Zʱ2y\ osG}_ڸ_aҵg!RFT(9;{ͳ^U3wBW>Nۏn]>ȻY7/Vsdp7v=)АmSP9@^,we7@ `[~tdt. -flHn3tLx?RxAHr'/=#9̥Y|T?ulrw Y4cb1'[pV4ҘYmZͪYh6G$p3?JBwd`1ԙp?ĠΦ2QUV^C**v\ZOAAD#!-e35œÃ. ]k==fi  <x('L6?{7_t@."wbe)qog4h`-NZjj~fSvBrؼL#PLb9['\Q > stream xڕZێ6}>f87$q 3D-uq~%$NjfX$UN)c/;F?w~ӎٟsNOWi^yBHDuO.HNT&i(U9&1k H[Tϥ!i;rȺ1k ݑ*\L*-Ůl3.*C+Q"C+YG 9M 7͵"2?CEi:w)<++i3XRt(~!`Zh&9coYuvlJ'uqK k߿K3_㊭iGPTP2k4/W&yݗriFv8tMX 8GTKlO'翥gT;dՁq'XeEBaF+z{BPuv\X$DLcRQ!q:X(fE !ï){, Wg My8 n~V$ I*A@' IL5p0fxŸ'-~G. +֔O+T$q@ a|!Twjwuj֝k03_4P`#Nykp8~rE|xm^Wc؆W!'t8;d}3TĨԭ -*7-!"J6>de[}= XܙTT6a5 v!1ȧW!EW]@@ CFr:V*;%2@A3h Zq6Ѹ*ƔiQ8|Jw ,Tje/s!)6B7zs_C;'or% u},cU>X}`pXHʅ.8Շ4k{ tL$Ǻn}3+ j H`n&A3dzf0sSbOcD檫(N=-]٥#; 46WRfIj,zGCFJBoP47OUe^шq{){ /{4);kbA<+`ltUh46Jo|p&RB @b 52팦#مE8nUvvP 5J@/HXnYB]í(ﶘ <^Mrs,{q8ecv͜%7r $M?]YB[x?H3t7\%v pygQoBET@χg]dLsozC J !pCo3 ~jGp[?GhZ H. o{:\L-B q+y8\Êm,7}swo(r]66b g12UE(`[;81дŊAL劭ɚhƀzP:GYy_f9p'KOuYbQI:n.A8A~s3?QMppѻok 46K(ע0(gr@C]AQD ļ._|Թ%Cj, O ^u׳l@@Möߔ(nHFyy[Bq73SڿEHmkvY:>zZyp* <TP/f,jOh9I]W'6BXhMmadJk|ǁp=8W\ @mbYLpG s?bFCEzCpG "W<83AG*[̺kg[ZX2OWMSpKC:H&~99ee|=^26~O-%VNT(<,=y|$ub),bi)|'f ny2o8 @=mcox:Ds&UMNYg skY VGݺ9w埆(C^쇱de4W۶NlqAۃ,>["/@1/u,8M 77 F~˞cY!R`i*+[a|qTz;1rBkv aN78[§HƉVԾ]M@jJ鋊qw}L Leg&}D} p@;Fj)y%9車<Tendstream endobj 605 0 obj 2820 endobj 610 0 obj <> stream x}RMo0WzuP* O1&d#`  g0!֛ QD42m9- pƷ>g?4X1&Thgi;n3"3c/\7endstream endobj 611 0 obj 477 endobj 3 0 obj <> endobj 129 0 obj <> /ColorSpace <> >>/Length 613 0 R >> stream x՛=mҝ+VlSR|Nnh/N;ih񌒴־M_0 ԔJUQZȍ9῭ן?^Ug[U7_{^^u|?nZS^߭/Pɯ__6uJ;5eWkWS^;JSqS+k~?MS_r4R_胯.gG^Y)r^<7:daEj_-9$}& Oծoh=KU; Kȝw`uPc֯,9 ܵ0/A,!2h'ϴGOFԆ5fCWQWyO[^??"דҟ_:YiIVs}ihտx/)x%|R:kݾ{VjZVe-O}_/Sln]hzTUEABm:Z_Ʋb3k!;ڒ651_ME*O6;ƨGˋ}42"BA",vS}゙J29YKR״3Z9-* ٰ(-k^6.k@dsa~(òk|3 S9:̮۟f#dKH)VbNð%IJdFJ5~U*jĿ| I4h=NI$y`H7d HVl Ys`:^0 VEA|%(j3E%SrQ|v^R||2z*uiGG$P3 {ɘ>kH|TUUkgjv]5dAM,>o9xriH> Ψi>b-;k[a'l^Ynƭdǻ"X$ŗОH@SI_y†cEcd_=p{+h'J/م;@dP6ʼ{L(fJyN2\8DiyZr'VCGHI!dI)He5bc0Urx * B7 ()d8N ?ֱi5G*EOn1_>b 2wUߒi r+c$״Vol`'0 M]TJo w;gZԬ@X>v9B.)W*076Ӣ.9=͐eaҚɶh #Mc\,4y"S3'ZʜA6}-t'1&DD'#kkb }ȣ>9JB-cܞ*Ok/js}w )'C~@ N)ѮCCkf/2rI.?p՛d,[I@=ez!YrᩯQf[hխL[F+l.f9[3!Sc9O-:YuU\*BBiv&;gKP8@:v\nNW& UVtnJWJFEҫQ'靆(gֻ?\-ɀ$nE_B4y^$dzǜ͹*jl$+iok錎,4LP 턄pK F5R.Gڹih4[;>ZfTmSƽ<\Ӵ6FjkPg~!6(1ͯlؒ>_hi+ܞG?yG$l̞H//Z3"+hxis4Hm6M[HݺoՃ~yuݧڞzDa-X^<Jf ZO7SNP5OKz| yK#wDED;V:/%20\9>FzIVbf,V[ k%+0MKsNz0?/F+K~:MZCqlY<]}|&`8dݝ᳡di@򛤚e޽:e9ƈht'21Yitc\)޷xNl3 kJ&HB>٬7hA k|к(%5(Q.mwǏ_ V Џ1v$zy)~gOu9iEÖC׎m:/ڐOǮbƖySw4УGLV@B|Y.+T^qKg4_)?=YL!;ISvzn7V#uzJ r~}.H> Dأ=gkÃ, f7;]ڣe?nd8;O1y&:yL26}]x 2R*{דaz説^zUHFbeKf]:ڣ{mC[q+\½Ȟc%(j$Vz 8uZ*jm*&rq+#ta!؝k?޴aP1ig4)1$z{SR,G+O帩-Aeg;A ۘ=V=LD?䳻sX[{7…߸챪McODu<.6AO J B_?8^MrD?4IBJYOBJ7Q:fHixֽavMݠиvmNmp>D*/Йv<.ps:p@JYq% Nq hӞ%r6wڬ%Ȼ#}b˛5yT FO`!jkVy{o4L3|<)Ŷ0WzxP M\<}TLW@M?}d0Gݚ^Lu]15=z:{D3u8y6HAp$z\a~N@.«sw-ARݷDQO떔*st)nm̧8בLq$qnt)`S1z'?i_K%sqaΗ룗buS^<.LUڬWyh u6Q`1@xs_/\2+"0W"nJG"*V X/|lK,K-xM1W`K_64.,=&9慜>16K os8$A%rtY1 Цmb,qfdƀcf˗c Y+G6Adi-xCTjdd}d #(&K.?|9ˀ nBGwx81|=!=PKi>kQ@ wOTb|=ɧMsсO2V:-P|aO;| Z$rQTHC{̠?쥼ove/&V%f^vʏ _\8(詡ۼIء5>cY۷^EܱEZvV'3h)2\5;xwV8FCN6#?ŠC)!郿Fe9\ָ@:!kKܐګ>®[?Zok ;%ǭ]ΚԗgM!Ӡ( ı/@ Q(\[Ni Þ8BFw7,?lTnA=<`)h/6#s @RLR NՐ t4m)mZ3pY{{U aJ m5n6Z gVk='œV,>k/^c'uwk}q +BwkEс︰nqi ̞tzxjJad:Wzфs-'{[sXHG$P9~{vTԶ!MTgWu=ǖ.Z$as)R\iOG-8} "@fW J_(${ΙMյ039Mtc4.RH zقuiI 륰m}/6zw7?¼'敜*1ǚE9 be Ͼף "50W^Xя){M=zs$wWZKM}ŌT -kxru59?"d:kZiHN~SX`Xoa8_Q@vXʑf3{Pu>ܨ34{5ʞ퇻m|QUQ՗:w5qfUֈzD4kD<~⪝4<(ݮie'sAO2W12X5;9I9xѾItwJ u|6Tݤ|3t'^#]rDթvq1[EpX/%k$2% 7x=P  E>c? TtuO8aأ{=^.EJYexRASH'q}5wĵ80s[r*m'yvD%2KxM{w;XD ]ۖKxb3M2#jvb^sp'Y|S\eYH:$ֿeY}]vKڥ@$@=Ry5eMĕĸeo׹C:7 #:7R>unP$MZ=an==SsoۗnЎ #*,q_wWg9L܈~'ƺEn[Z՘E;5|)r(rͻ*7crX;n+T:unkǼunݫ=-tl:n9\).Bޖ[psunLunVu:F:iu=کs`s@sB70Sq]? ,=.t#yB=͏:7R:=unhΏ:Թ(=aGz'^zrvB -tsn[Dx-4һ=*)sy#*9q]mV˖>,[j[Ɖ*:2C3~Fw3Z`rs6 >N{Hxv{ąw{V*7EgUnA_jUnnvr 8]VUn`En*.rP-r .r[ӧ.revPke-S^𔹹G{6! iWz׹ўM֭Le:n~q ~zWn3#gun2`iWϢ`?!~|;ngO&~/j܆ߴρ9 ]Mig:HgkK۹8I.a}He}Vrf}h(>g]0>Gě9p>?7τ\F/ E e]ևuYE>X*}ܽk-I ߤiؤN(g {WV|0p8}g-Jޜ |p>^|s>Yr.Fڽ52"̑"a-Y|tq @se0?e~?߼ƛkgEvik,8`)·99PKt05?8m 糸x2>H }㺜nxs>as>tYǸp>\g=.gE&} m1`u0M 3tu}>sY9lGpih>qI,Zޜρ9 >p>o·/ә,}Ic}É 2>G[ſT@WȗNt ) WܽGim| =z1r_7iNQ):Ds/iF'Q3pМy9\rC\:\x 5Ə6NV|mpK`hF+>wn\|==yx>IiR&CDQd{\p>NCYǼTǭ(nV)K+`>>E =^Ծ78 l0OF!sH [񃱹UtWX[W3Q38.rF?VlV8)[WXO5A рzGqhW-?P .=ygWRGT7ɾ[)#_ ƒPK)~PLEwbPp)=:N'7z9dn:vD:/ieendstream endobj 613 0 obj 6861 endobj 614 0 obj <> endobj 615 0 obj [/ICCBased 616 0 R ] endobj 616 0 obj <>stream HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 N')].uJr  wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 252 0 obj <> endobj 617 0 obj <> endobj 618 0 obj <> endobj 619 0 obj <> stream x]POq(LiLιd h;L0zMFŘE޾~~a ]$Eoi!.u(bKیa:t!njԴjgwy/>.c:uma6]-<)[44)<õsjǐg]R=d^SX>U_r1[z>_PvUE=l绰}~eɹX!ۮqkO5Z؂V#; {~d? v.%bWN]O- lbt B)t B)64,0 ,0 ,0 Ҧ)m Ҧ)m Ҧ)m Ҧ)m Ҧ)= ң(=:{8C #g1Hg3tF8#Hg3tF8#xdѴE"=`0 `0 `0 `0  2>Gs4 6 34: N 34 f 3t~w~w~w~w~w~y:xձ ou]eީ};FӦͬz?38endstream endobj 620 0 obj 563 endobj 385 0 obj <> endobj 621 0 obj <> endobj 622 0 obj <> endobj 623 0 obj <> stream x]n@> endobj 625 0 obj <> endobj 626 0 obj <> endobj 627 0 obj <> stream x]Mk0Ca{~DX,K=]h2@MBtCЃf;LJK1ʟnaTuuH@|1 $7[ 8 I `M]F%WD9nm޴  *8F{7!'XdKF|LqutrDR&I\_.$;C"IbE›8nm?ZH?Vک endstream endobj 628 0 obj 286 endobj 447 0 obj <> endobj 629 0 obj <> endobj 630 0 obj <> endobj 631 0 obj <> stream x]N0E @EI43 EP "=)'Ezrb[wC+&3rb܌I>l}?- tw1z,sz;gݟ7ק$LS8I禎8߲?,Y../^Lzѿ(&K8al$lmu"[+Vv Ik4ف%r>_-gC+R|l6r|R%)2>i}B4OP^WʨCZP: f[2Hݨ$$|/΁wzn OVO''ÓՓdd1w!Bmߖb8vBIa]]endstream endobj 632 0 obj 389 endobj 128 0 obj <> endobj 633 0 obj <> endobj 634 0 obj <> endobj 635 0 obj <> stream x]@D|ispMOdYZ9ZŇ$%))H9> endobj 637 0 obj <> endobj 638 0 obj <> endobj 639 0 obj <> stream x]n0 @0;0(иRթZ۪}$Cп_NSLJcm`='4Fzr$tl;k#> endobj 641 0 obj <> endobj 642 0 obj <> endobj 643 0 obj <> stream x]j0D)) B}hdi bI*RaHopiv[WL MzX_ȩjp0 YS.Sce )`UQ7@c/,rDGTI~8yBTPCy[RN q8yIu;"dZ> endobj 645 0 obj <> endobj 646 0 obj <> endobj 647 0 obj <> stream x]n0 @0;0(q+!SUeHL4 п_N8KLJSL_czN4Fjr$ulZkܜ#kV,SiZ=ͭ<vG"e|nrv|3Z{}u~C;D4{աwבO (^ CU"OBC!КciSFWN)&"ց}l23̳~E*eNW+bW!Wf 0o[bͬGBf$ng: tMURW|Kue_L{endstream endobj 648 0 obj 345 endobj 130 0 obj <> endobj 649 0 obj <> endobj 650 0 obj <> endobj 651 0 obj <> stream x]͊`}0]X?Η" h;j.)tgq>~xNn'y Ul}1ݼ|yi4}jϩ9p'E~w霏/mUOn<}zَKܞӬXSFU~^9 UWS_Vy(}.V:En-GvMfe9{^ha :؁^G#bW]3;v3 0  0 ([6M)t B)%D;4/ /+ Ҭ0+ Ҭ0+ Ҭ0+ Ҭ0+ Ҭ0+ Ҭ0+ Ҭ0+ q憙ooool0f9m9m9m9m9m9g똭p:g똭0;g똭<;^(+}Uam6ϡKz}0ABendstream endobj 652 0 obj 578 endobj 135 0 obj <> endobj 653 0 obj <> endobj 654 0 obj <> endobj 655 0 obj <> stream x]J0y 4 B),e&IHC$-ac}s0?Rdf'0߹%yݼ6ZyΈ=JK@Ҥ` W[sLF%䗐[`6>ItJl/=PRU >"GfDJo"A ө"⇻!K3Z$_)iҎmZpu/fұhZiR`~Gendstream endobj 656 0 obj 259 endobj 608 0 obj <> >> endobj 607 0 obj <> >> endobj 598 0 obj <> >> endobj 597 0 obj <> >> endobj 596 0 obj <> endobj 595 0 obj <> endobj 594 0 obj <> >> endobj 589 0 obj <> >> endobj 588 0 obj <> >> endobj 587 0 obj <> >> endobj 586 0 obj <> >> endobj 585 0 obj <> >> endobj 584 0 obj <> >> endobj 583 0 obj <> >> endobj 582 0 obj <> >> endobj 581 0 obj <> >> endobj 580 0 obj <> >> endobj 575 0 obj <> >> endobj 570 0 obj <> >> endobj 569 0 obj <> >> endobj 568 0 obj <> >> endobj 542 0 obj <> endobj 541 0 obj <> endobj 540 0 obj <> endobj 531 0 obj <> endobj 530 0 obj <> endobj 525 0 obj <> endobj 516 0 obj <> endobj 503 0 obj <> endobj 498 0 obj <> endobj 497 0 obj <> endobj 492 0 obj <> endobj 491 0 obj <> endobj 486 0 obj <> endobj 485 0 obj <> endobj 484 0 obj <> endobj 479 0 obj <> endobj 478 0 obj <> endobj 465 0 obj <> endobj 464 0 obj <> endobj 459 0 obj <> endobj 449 0 obj <> endobj 448 0 obj <> endobj 430 0 obj <> endobj 429 0 obj <> endobj 424 0 obj <> endobj 423 0 obj <> endobj 422 0 obj <> endobj 421 0 obj <> endobj 412 0 obj <> endobj 403 0 obj <> endobj 398 0 obj <> endobj 397 0 obj <> endobj 396 0 obj <> endobj 395 0 obj <> endobj 394 0 obj <> endobj 389 0 obj <> endobj 388 0 obj <> endobj 387 0 obj <> endobj 376 0 obj <> endobj 375 0 obj <> endobj 374 0 obj <> endobj 373 0 obj <> endobj 372 0 obj <> endobj 371 0 obj <> endobj 370 0 obj <> endobj 369 0 obj <> endobj 368 0 obj <> endobj 367 0 obj <> endobj 366 0 obj <> endobj 365 0 obj <> endobj 360 0 obj <> endobj 359 0 obj <> endobj 358 0 obj <> endobj 357 0 obj <> endobj 356 0 obj <> endobj 355 0 obj <> endobj 354 0 obj <> endobj 353 0 obj <> endobj 352 0 obj <> endobj 351 0 obj <> endobj 350 0 obj <> endobj 349 0 obj <> endobj 348 0 obj <> endobj 347 0 obj <> endobj 346 0 obj <> endobj 345 0 obj <> endobj 344 0 obj <> endobj 343 0 obj <> endobj 342 0 obj <> endobj 341 0 obj <> endobj 340 0 obj <> endobj 339 0 obj <> endobj 338 0 obj <> endobj 337 0 obj <> endobj 336 0 obj <> endobj 335 0 obj <> endobj 334 0 obj <> endobj 333 0 obj <> endobj 332 0 obj <> endobj 331 0 obj <> endobj 330 0 obj <> endobj 329 0 obj <> endobj 328 0 obj <> endobj 327 0 obj <> endobj 326 0 obj <> endobj 325 0 obj <> endobj 324 0 obj <> endobj 323 0 obj <> endobj 322 0 obj <> endobj 321 0 obj <> endobj 320 0 obj <> endobj 319 0 obj <> endobj 318 0 obj <> endobj 317 0 obj <> endobj 316 0 obj <> endobj 315 0 obj <> endobj 314 0 obj <> endobj 313 0 obj <> endobj 312 0 obj <> endobj 311 0 obj <> endobj 310 0 obj <> endobj 309 0 obj <> endobj 308 0 obj <> endobj 307 0 obj <> endobj 306 0 obj <> endobj 305 0 obj <> endobj 304 0 obj <> endobj 303 0 obj <> endobj 302 0 obj <> endobj 301 0 obj <> endobj 300 0 obj <> endobj 299 0 obj <> endobj 298 0 obj <> endobj 297 0 obj <> endobj 296 0 obj <> endobj 295 0 obj <> endobj 294 0 obj <> endobj 293 0 obj <> endobj 292 0 obj <> endobj 291 0 obj <> endobj 290 0 obj <> endobj 289 0 obj <> endobj 288 0 obj <> endobj 287 0 obj <> endobj 286 0 obj <> endobj 285 0 obj <> endobj 284 0 obj <> endobj 283 0 obj <> endobj 282 0 obj <> endobj 281 0 obj <> endobj 280 0 obj <> endobj 279 0 obj <> endobj 278 0 obj <> endobj 277 0 obj <> endobj 276 0 obj <> endobj 275 0 obj <> endobj 274 0 obj <> endobj 273 0 obj <> endobj 272 0 obj <> endobj 271 0 obj <> endobj 270 0 obj <> endobj 269 0 obj <> endobj 268 0 obj <> endobj 267 0 obj <> endobj 266 0 obj <> endobj 265 0 obj <> endobj 264 0 obj <> endobj 263 0 obj <> endobj 262 0 obj <> endobj 261 0 obj <> endobj 260 0 obj <> endobj 259 0 obj <> endobj 258 0 obj <> endobj 257 0 obj <> endobj 256 0 obj <> endobj 255 0 obj <> endobj 254 0 obj <> endobj 253 0 obj <> endobj 247 0 obj <> endobj 246 0 obj <> endobj 245 0 obj <> endobj 244 0 obj <> endobj 243 0 obj <> endobj 242 0 obj <> endobj 241 0 obj <> endobj 240 0 obj <> endobj 239 0 obj <> endobj 238 0 obj <> endobj 237 0 obj <> endobj 236 0 obj <> endobj 235 0 obj <> endobj 234 0 obj <> endobj 233 0 obj <> endobj 232 0 obj <> endobj 231 0 obj <> endobj 230 0 obj <> endobj 229 0 obj <> endobj 228 0 obj <> endobj 227 0 obj <> endobj 226 0 obj <> endobj 225 0 obj <> endobj 224 0 obj <> endobj 223 0 obj <> endobj 222 0 obj <> endobj 221 0 obj <> endobj 220 0 obj <> endobj 219 0 obj <> endobj 218 0 obj <> endobj 217 0 obj <> endobj 216 0 obj <> endobj 215 0 obj <> endobj 214 0 obj <> endobj 213 0 obj <> endobj 212 0 obj <> endobj 211 0 obj <> endobj 210 0 obj <> endobj 209 0 obj <> endobj 208 0 obj <> endobj 207 0 obj <> endobj 206 0 obj <> endobj 205 0 obj <> endobj 204 0 obj <> endobj 203 0 obj <> endobj 202 0 obj <> endobj 201 0 obj <> endobj 200 0 obj <> endobj 199 0 obj <> endobj 198 0 obj <> endobj 197 0 obj <> endobj 196 0 obj <> endobj 195 0 obj <> endobj 194 0 obj <> endobj 193 0 obj <> endobj 192 0 obj <> endobj 191 0 obj <> endobj 190 0 obj <> endobj 189 0 obj <> endobj 188 0 obj <> endobj 187 0 obj <> endobj 186 0 obj <> endobj 185 0 obj <> endobj 184 0 obj <> endobj 183 0 obj <> endobj 182 0 obj <> endobj 181 0 obj <> endobj 180 0 obj <> endobj 179 0 obj <> endobj 178 0 obj <> endobj 177 0 obj <> endobj 176 0 obj <> endobj 175 0 obj <> endobj 174 0 obj <> endobj 173 0 obj <> endobj 172 0 obj <> endobj 171 0 obj <> endobj 170 0 obj <> endobj 169 0 obj <> endobj 168 0 obj <> endobj 167 0 obj <> endobj 166 0 obj <> endobj 165 0 obj <> endobj 164 0 obj <> endobj 163 0 obj <> endobj 162 0 obj <> endobj 161 0 obj <> endobj 160 0 obj <> endobj 159 0 obj <> endobj 158 0 obj <> endobj 157 0 obj <> endobj 156 0 obj <> endobj 155 0 obj <> endobj 154 0 obj <> endobj 153 0 obj <> endobj 152 0 obj <> endobj 151 0 obj <> endobj 150 0 obj <> endobj 149 0 obj <> endobj 148 0 obj <> endobj 147 0 obj <> endobj 146 0 obj <> endobj 136 0 obj <> >> endobj 1 0 obj <> 3 <

> 4 <

> 5 <

> 6 <> ] >> /PageMode /UseOutlines /OpenAction [122 0 R /XYZ 0 792 0] /Outlines 4 0 R /Names 126 0 R >> endobj 2 0 obj <> endobj 657 0 obj <> endobj 658 0 obj <> endobj 659 0 obj <> endobj 660 0 obj <> endobj 661 0 obj <> endobj 122 0 obj <> endobj 125 0 obj <> /XObject <> >> endobj 662 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 663 0 obj 36 endobj 131 0 obj <> endobj 134 0 obj <> >> endobj 664 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 665 0 obj 36 endobj 137 0 obj <> endobj 140 0 obj <> >> endobj 666 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 667 0 obj 36 endobj 141 0 obj <> endobj 144 0 obj <> >> endobj 668 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 669 0 obj 36 endobj 248 0 obj <> endobj 251 0 obj <> >> endobj 670 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 671 0 obj 36 endobj 361 0 obj <> endobj 364 0 obj <> >> endobj 672 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 673 0 obj 36 endobj 377 0 obj <> endobj 380 0 obj <> >> endobj 674 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 675 0 obj 36 endobj 381 0 obj <> endobj 384 0 obj <> >> endobj 676 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 677 0 obj 36 endobj 390 0 obj <> endobj 393 0 obj <> >> endobj 678 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 679 0 obj 36 endobj 399 0 obj <> endobj 402 0 obj <> >> endobj 680 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 681 0 obj 36 endobj 404 0 obj <> endobj 407 0 obj <> >> endobj 682 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 683 0 obj 36 endobj 408 0 obj <> endobj 411 0 obj <> >> endobj 684 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 685 0 obj 36 endobj 413 0 obj <> endobj 416 0 obj <> >> endobj 686 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 687 0 obj 36 endobj 417 0 obj <> endobj 420 0 obj <> >> endobj 688 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 689 0 obj 36 endobj 425 0 obj <> endobj 428 0 obj <> >> endobj 690 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 691 0 obj 36 endobj 431 0 obj <> endobj 434 0 obj <> >> endobj 692 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 693 0 obj 36 endobj 435 0 obj <> endobj 438 0 obj <> >> endobj 694 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 695 0 obj 36 endobj 439 0 obj <> endobj 442 0 obj <> >> endobj 696 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 697 0 obj 36 endobj 443 0 obj <> endobj 446 0 obj <> >> endobj 698 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 699 0 obj 36 endobj 450 0 obj <> endobj 453 0 obj <> >> endobj 700 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 701 0 obj 36 endobj 455 0 obj <> endobj 458 0 obj <> >> endobj 702 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 703 0 obj 36 endobj 460 0 obj <> endobj 463 0 obj <> >> endobj 704 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 705 0 obj 36 endobj 466 0 obj <> endobj 469 0 obj <> >> endobj 706 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 707 0 obj 36 endobj 470 0 obj <> endobj 473 0 obj <> >> endobj 708 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 709 0 obj 36 endobj 474 0 obj <> endobj 477 0 obj <> >> endobj 710 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 711 0 obj 36 endobj 480 0 obj <> endobj 483 0 obj <> >> endobj 712 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 713 0 obj 36 endobj 487 0 obj <> endobj 490 0 obj <> >> endobj 714 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 715 0 obj 36 endobj 493 0 obj <> endobj 496 0 obj <> >> endobj 716 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 717 0 obj 36 endobj 499 0 obj <> endobj 502 0 obj <> >> endobj 718 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 719 0 obj 36 endobj 504 0 obj <> endobj 507 0 obj <> >> endobj 720 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 721 0 obj 36 endobj 508 0 obj <> endobj 511 0 obj <> >> endobj 722 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 723 0 obj 36 endobj 512 0 obj <> endobj 515 0 obj <> >> endobj 724 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 725 0 obj 36 endobj 517 0 obj <> endobj 520 0 obj <> >> endobj 726 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 727 0 obj 36 endobj 521 0 obj <> endobj 524 0 obj <> >> endobj 728 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 729 0 obj 36 endobj 526 0 obj <> endobj 529 0 obj <> >> endobj 730 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 731 0 obj 36 endobj 532 0 obj <> endobj 535 0 obj <> >> endobj 732 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 733 0 obj 36 endobj 536 0 obj <> endobj 539 0 obj <> >> endobj 734 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 735 0 obj 36 endobj 543 0 obj <> endobj 546 0 obj <> >> endobj 736 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 737 0 obj 36 endobj 547 0 obj <> endobj 550 0 obj <> >> endobj 738 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 739 0 obj 36 endobj 551 0 obj <> endobj 554 0 obj <> >> endobj 740 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 741 0 obj 36 endobj 555 0 obj <> endobj 558 0 obj <> >> endobj 742 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 743 0 obj 36 endobj 560 0 obj <> endobj 563 0 obj <> >> endobj 744 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 745 0 obj 36 endobj 564 0 obj <> endobj 567 0 obj <> >> endobj 746 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 747 0 obj 36 endobj 571 0 obj <> endobj 574 0 obj <> >> endobj 748 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 749 0 obj 36 endobj 576 0 obj <> endobj 579 0 obj <> >> endobj 750 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 751 0 obj 36 endobj 590 0 obj <> endobj 593 0 obj <> >> endobj 752 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 753 0 obj 36 endobj 599 0 obj <> endobj 602 0 obj <> >> endobj 754 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 755 0 obj 36 endobj 603 0 obj <> endobj 606 0 obj <> >> endobj 756 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 757 0 obj 36 endobj 609 0 obj <> endobj 612 0 obj <> >> endobj 758 0 obj <> stream x+2P0P2349`2\ y\endstream endobj 759 0 obj 36 endobj 4 0 obj <> endobj 113 0 obj <> endobj 115 0 obj <> endobj 117 0 obj <> endobj 116 0 obj <> endobj 114 0 obj <> endobj 121 0 obj <> endobj 120 0 obj <> endobj 119 0 obj <> endobj 118 0 obj <> endobj 77 0 obj <> endobj 94 0 obj <> endobj 95 0 obj <> endobj 96 0 obj <> endobj 99 0 obj <> endobj 98 0 obj <> endobj 97 0 obj <> endobj 100 0 obj <> endobj 91 0 obj <> endobj 93 0 obj <> endobj 92 0 obj <> endobj 88 0 obj <> endobj 90 0 obj <> endobj 89 0 obj <> endobj 85 0 obj <> endobj 87 0 obj <> endobj 86 0 obj <> endobj 84 0 obj <> endobj 79 0 obj <> endobj 83 0 obj <> endobj 82 0 obj <> endobj 81 0 obj <> endobj 80 0 obj <> endobj 78 0 obj <> endobj 111 0 obj <> endobj 112 0 obj <> endobj 106 0 obj <> endobj 107 0 obj <> endobj 110 0 obj <> endobj 109 0 obj <> endobj 108 0 obj <> endobj 101 0 obj <> endobj 105 0 obj <> endobj 104 0 obj <> endobj 103 0 obj <> endobj 102 0 obj <> endobj 25 0 obj <> endobj 34 0 obj <> endobj 35 0 obj <> endobj 37 0 obj <> endobj 36 0 obj <> endobj 66 0 obj <> endobj 67 0 obj <> endobj 69 0 obj <> endobj 68 0 obj <> endobj 62 0 obj <> endobj 65 0 obj <> endobj 64 0 obj <> endobj 63 0 obj <> endobj 29 0 obj <> endobj 33 0 obj <> endobj 32 0 obj <> endobj 31 0 obj <> endobj 30 0 obj <> endobj 26 0 obj <> endobj 27 0 obj <> endobj 28 0 obj <> endobj 58 0 obj <> endobj 59 0 obj <> endobj 61 0 obj <> endobj 60 0 obj <> endobj 54 0 obj <> endobj 57 0 obj <> endobj 56 0 obj <> endobj 55 0 obj <> endobj 50 0 obj <> endobj 51 0 obj <> endobj 53 0 obj <> endobj 52 0 obj <> endobj 46 0 obj <> endobj 49 0 obj <> endobj 48 0 obj <> endobj 47 0 obj <> endobj 76 0 obj <> endobj 75 0 obj <> endobj 42 0 obj <> endobj 43 0 obj <> endobj 45 0 obj <> endobj 44 0 obj <> endobj 74 0 obj <> endobj 38 0 obj <> endobj 41 0 obj <> endobj 40 0 obj <> endobj 39 0 obj <> endobj 70 0 obj <> endobj 73 0 obj <> endobj 72 0 obj <> endobj 71 0 obj <> endobj 7 0 obj <> endobj 24 0 obj <> endobj 23 0 obj <> endobj 22 0 obj <> endobj 21 0 obj <> endobj 20 0 obj <> endobj 19 0 obj <> endobj 16 0 obj <> endobj 18 0 obj <> endobj 17 0 obj <> endobj 12 0 obj <> endobj 15 0 obj <> endobj 14 0 obj <> endobj 13 0 obj <> endobj 8 0 obj <> endobj 11 0 obj <> endobj 10 0 obj <> endobj 9 0 obj <> endobj 6 0 obj <> endobj 5 0 obj <> endobj 126 0 obj <> endobj 127 0 obj <> endobj 1475 0 obj <> endobj 1478 0 obj <> endobj 1479 0 obj <> endobj 1480 0 obj <> endobj 1481 0 obj <> endobj 1482 0 obj <> endobj 1483 0 obj <> endobj 1484 0 obj <> endobj 1485 0 obj <> endobj 1486 0 obj <> endobj 1487 0 obj <> endobj 1488 0 obj <> endobj 1489 0 obj <> endobj 1490 0 obj <> endobj 1491 0 obj <> endobj 1492 0 obj <> endobj 1493 0 obj <> endobj 1476 0 obj <> endobj 1494 0 obj <> endobj 1495 0 obj <> endobj 1496 0 obj <> endobj 1497 0 obj <> endobj 1498 0 obj <> endobj 1499 0 obj <> endobj 1500 0 obj <> endobj 1501 0 obj <> endobj 1502 0 obj <> endobj 1503 0 obj <> endobj 1504 0 obj <> endobj 1505 0 obj <> endobj 1506 0 obj <> endobj 1507 0 obj <> endobj 1508 0 obj <> endobj 1509 0 obj <> endobj 1477 0 obj <> endobj 1510 0 obj <> endobj 1511 0 obj <> endobj 1512 0 obj <> endobj 1513 0 obj <> endobj 1514 0 obj <> endobj 1515 0 obj <> endobj 1516 0 obj <> endobj 1517 0 obj <> endobj 1518 0 obj <> endobj 1519 0 obj <> endobj 1520 0 obj <> endobj 1521 0 obj <> endobj 1522 0 obj <> endobj 1388 0 obj <
> endobj 1331 0 obj <> endobj 1441 0 obj <> endobj 806 0 obj <> endobj 834 0 obj <> endobj 1141 0 obj <> endobj 777 0 obj <> endobj 812 0 obj <> endobj 852 0 obj <> endobj 937 0 obj <> endobj 1401 0 obj <> endobj 1376 0 obj <> endobj 1389 0 obj <> endobj 1214 0 obj <> endobj 808 0 obj <> endobj 1409 0 obj <> endobj 1171 0 obj <> endobj 1077 0 obj <> endobj 1348 0 obj <> endobj 1267 0 obj <> endobj 781 0 obj <> endobj 771 0 obj <> endobj 1321 0 obj <> endobj 1101 0 obj <> endobj 1397 0 obj <> endobj 1005 0 obj <> endobj 930 0 obj <> endobj 1412 0 obj <> endobj 1328 0 obj <> endobj 1103 0 obj <> endobj 1327 0 obj <> endobj 856 0 obj <> endobj 1289 0 obj <> endobj 1099 0 obj <> endobj 1270 0 obj <> endobj 1207 0 obj <> endobj 911 0 obj <> endobj 1146 0 obj <> endobj 761 0 obj <> endobj 1057 0 obj <> endobj 1443 0 obj <> endobj 872 0 obj <> endobj 1471 0 obj <> endobj 819 0 obj <> endobj 901 0 obj <> endobj 770 0 obj <> endobj 1246 0 obj <> endobj 894 0 obj <> endobj 1347 0 obj <> endobj 851 0 obj <> endobj 1449 0 obj <> endobj 838 0 obj <> endobj 1119 0 obj <> endobj 1079 0 obj <> endobj 1269 0 obj <> endobj 891 0 obj <> endobj 774 0 obj <> endobj 1258 0 obj <> endobj 927 0 obj <> endobj 1036 0 obj <> endobj 1431 0 obj <> endobj 1140 0 obj <> endobj 1175 0 obj <> endobj 1373 0 obj <> endobj 1340 0 obj <> endobj 1311 0 obj <> endobj 1148 0 obj <> endobj 1177 0 obj <> endobj 864 0 obj <> endobj 862 0 obj <> endobj 853 0 obj <> endobj 842 0 obj <> endobj 839 0 obj <> endobj 830 0 obj <> endobj 1322 0 obj <> endobj 1320 0 obj <> endobj 1309 0 obj <> endobj 1433 0 obj <> endobj 921 0 obj <> endobj 906 0 obj <> endobj 840 0 obj <> endobj 1256 0 obj <> endobj 1220 0 obj <> endobj 1219 0 obj <> endobj 1206 0 obj <> endobj 1183 0 obj <> endobj 1466 0 obj <> endobj 1462 0 obj <> endobj 1239 0 obj <> endobj 1202 0 obj <> endobj 1213 0 obj <> endobj 1203 0 obj <> endobj 1038 0 obj <> endobj 996 0 obj <> endobj 948 0 obj <> endobj 936 0 obj <> endobj 1091 0 obj <> endobj 1073 0 obj <> endobj 1049 0 obj <> endobj 1439 0 obj <> endobj 1121 0 obj <> endobj 978 0 obj <> endobj 972 0 obj <> endobj 955 0 obj <> endobj 909 0 obj <> endobj 1377 0 obj <> endobj 1375 0 obj <> endobj 1390 0 obj <> endobj 1139 0 obj <> endobj 1128 0 obj <> endobj 797 0 obj <> endobj 780 0 obj <> endobj 788 0 obj <> endobj 1167 0 obj <> endobj 1144 0 obj <> endobj 1064 0 obj <> endobj 1051 0 obj <> endobj 1034 0 obj <> endobj 1010 0 obj <> endobj 995 0 obj <> endobj 976 0 obj <> endobj 1137 0 obj <> endobj 1065 0 obj <> endobj 1062 0 obj <> endobj 1048 0 obj <> endobj 1029 0 obj <> endobj 1011 0 obj <> endobj 818 0 obj <> endobj 1283 0 obj <> endobj 1243 0 obj <> endobj 1236 0 obj <> endobj 931 0 obj <> endobj 899 0 obj <> endobj 877 0 obj <> endobj 1398 0 obj <> endobj 1124 0 obj <> endobj 1104 0 obj <> endobj 1082 0 obj <> endobj 1126 0 obj <> endobj 1114 0 obj <> endobj 816 0 obj <> endobj 815 0 obj <> endobj 807 0 obj <> endobj 794 0 obj <> endobj 776 0 obj <> endobj 1254 0 obj <> endobj 907 0 obj <> endobj 809 0 obj <> endobj 1281 0 obj <> endobj 1255 0 obj <> endobj 1228 0 obj <> endobj 1208 0 obj <> endobj 1052 0 obj <> endobj 1100 0 obj <> endobj 1066 0 obj <> endobj 1040 0 obj <> endobj 1158 0 obj <> endobj 1112 0 obj <> endobj 775 0 obj <> endobj 1205 0 obj <> endobj 1179 0 obj <> endobj 1174 0 obj <> endobj 1333 0 obj <> endobj 1092 0 obj <> endobj 1083 0 obj <> endobj 1465 0 obj <> endobj 957 0 obj <> endobj 925 0 obj <> endobj 1405 0 obj <> endobj 1393 0 obj <> endobj 1084 0 obj <> endobj 1050 0 obj <> endobj 1043 0 obj <> endobj 987 0 obj <> endobj 1424 0 obj <> endobj 1413 0 obj <> endobj 1383 0 obj <> endobj 1074 0 obj <> endobj 1072 0 obj <> endobj 1023 0 obj <> endobj 1442 0 obj <> endobj 1429 0 obj <> endobj 1425 0 obj <> endobj 1155 0 obj <> endobj 1149 0 obj <> endobj 1110 0 obj <> endobj 1076 0 obj <> endobj 900 0 obj <> endobj 885 0 obj <> endobj 846 0 obj <> endobj 821 0 obj <> endobj 1302 0 obj <> endobj 1261 0 obj <> endobj 1222 0 obj <> endobj 924 0 obj <> endobj 912 0 obj <> endobj 878 0 obj <> endobj 1364 0 obj <> endobj 1353 0 obj <> endobj 1276 0 obj <> endobj 1024 0 obj <> endobj 961 0 obj <> endobj 935 0 obj <> endobj 933 0 obj <> endobj 1378 0 obj <> endobj 1352 0 obj <> endobj 1316 0 obj <> endobj 1071 0 obj <> endobj 1025 0 obj <> endobj 982 0 obj <> endobj 981 0 obj <> endobj 1447 0 obj <> endobj 1430 0 obj <> endobj 1395 0 obj <> endobj 1384 0 obj <> endobj 1111 0 obj <> endobj 1027 0 obj <> endobj 1012 0 obj <> endobj 1446 0 obj <> endobj 1423 0 obj <> endobj 865 0 obj <> endobj 1262 0 obj <> endobj 958 0 obj <> endobj 938 0 obj <> endobj 890 0 obj <> endobj 1341 0 obj <> endobj 1323 0 obj <> endobj 1274 0 obj <> endobj 1003 0 obj <> endobj 1402 0 obj <> endobj 1379 0 obj <> endobj 1313 0 obj <> endobj 1006 0 obj <> endobj 1004 0 obj <> endobj 962 0 obj <> endobj 1427 0 obj <> endobj 1396 0 obj <> endobj 1349 0 obj <> endobj 1102 0 obj <> endobj 1042 0 obj <> endobj 1009 0 obj <> endobj 1007 0 obj <> endobj 854 0 obj <> endobj 801 0 obj <> endobj 799 0 obj <> endobj 773 0 obj <> endobj 1210 0 obj <> endobj 1304 0 obj <> endobj 1301 0 obj <> endobj 1286 0 obj <> endobj 1273 0 obj <> endobj 1244 0 obj <> endobj 1221 0 obj <> endobj 1196 0 obj <> endobj 932 0 obj <> endobj 910 0 obj <> endobj 844 0 obj <> endobj 1293 0 obj <> endobj 1275 0 obj <> endobj 1247 0 obj <> endobj 1350 0 obj <> endobj 1312 0 obj <> endobj 1294 0 obj <> endobj 1037 0 obj <> endobj 963 0 obj <> endobj 1428 0 obj <> endobj 1403 0 obj <> endobj 1391 0 obj <> endobj 1380 0 obj <> endobj 1365 0 obj <> endobj 1343 0 obj <> endobj 1152 0 obj <> endobj 1151 0 obj <> endobj 1143 0 obj <> endobj 1098 0 obj <> endobj 841 0 obj <> endobj 765 0 obj <> endobj 1472 0 obj <> endobj 1188 0 obj <> endobj 1185 0 obj <> endobj 1170 0 obj <> endobj 802 0 obj <> endobj 800 0 obj <> endobj 1284 0 obj <> endobj 1271 0 obj <> endobj 1260 0 obj <> endobj 888 0 obj <> endobj 867 0 obj <> endobj 855 0 obj <> endobj 833 0 obj <> endobj 1332 0 obj <> endobj 1315 0 obj <> endobj 1245 0 obj <> endobj 980 0 obj <> endobj 1039 0 obj <> endobj 974 0 obj <> endobj 940 0 obj <> endobj 778 0 obj <> endobj 1460 0 obj <> endobj 1438 0 obj <> endobj 960 0 obj <> endobj 791 0 obj <> endobj 1212 0 obj <> endobj 792 0 obj <> endobj 829 0 obj <> endobj 1229 0 obj <> endobj 1125 0 obj <> endobj 1411 0 obj <> endobj 1248 0 obj <> endobj 971 0 obj <> endobj 1187 0 obj <> endobj 949 0 obj <> endobj 939 0 obj <> endobj 1360 0 obj <> endobj 826 0 obj <> endobj 1355 0 obj <> endobj 1468 0 obj <> endobj 1116 0 obj <> endobj 1374 0 obj <> endobj 1437 0 obj <> endobj 1145 0 obj <> endobj 1310 0 obj <> endobj 1392 0 obj <> endobj 968 0 obj <> endobj 1030 0 obj <> endobj 954 0 obj <> endobj 1415 0 obj <> endobj 1193 0 obj <> endobj 876 0 obj <> endobj 1204 0 obj <> endobj 1406 0 obj <> endobj 1189 0 obj <> endobj 836 0 obj <> endobj 1291 0 obj <> endobj 1008 0 obj <> endobj 1089 0 obj <> endobj 875 0 obj <> endobj 889 0 obj <> endobj 1240 0 obj <> endobj 1061 0 obj <> endobj 1469 0 obj <> endobj 1432 0 obj <> endobj 1168 0 obj <> endobj 1453 0 obj <> endobj 1053 0 obj <> endobj 1470 0 obj <> endobj 929 0 obj <> endobj 979 0 obj <> endobj 928 0 obj <> endobj 1463 0 obj <> endobj 860 0 obj <> endobj 983 0 obj <> endobj 1080 0 obj <> endobj 1090 0 obj <> endobj 827 0 obj <> endobj 1178 0 obj <> endobj 863 0 obj <> endobj 1173 0 obj <> endobj 1230 0 obj <> endobj 1131 0 obj <> endobj 848 0 obj <> endobj 873 0 obj <> endobj 975 0 obj <> endobj 1344 0 obj <> endobj 1211 0 obj <> endobj 1381 0 obj <> endobj 908 0 obj <> endobj 1394 0 obj <> endobj 1399 0 obj <> endobj 1020 0 obj <> endobj 1059 0 obj <> endobj 1300 0 obj <> endobj 1063 0 obj <> endobj 859 0 obj <> endobj 1022 0 obj <> endobj 1436 0 obj <> endobj 1226 0 obj <> endobj 1351 0 obj <> endobj 1324 0 obj <> endobj 1295 0 obj <> endobj 1129 0 obj <> endobj 1160 0 obj <> endobj 845 0 obj <> endobj 843 0 obj <> endobj 831 0 obj <> endobj 823 0 obj <> endobj 817 0 obj <> endobj 810 0 obj <> endobj 1305 0 obj <> endobj 1303 0 obj <> endobj 1292 0 obj <> endobj 1420 0 obj <> endobj 898 0 obj <> endobj 884 0 obj <> endobj 820 0 obj <> endobj 1234 0 obj <> endobj 1199 0 obj <> endobj 1198 0 obj <> endobj 1184 0 obj <> endobj 1162 0 obj <> endobj 1451 0 obj <> endobj 1448 0 obj <> endobj 1216 0 obj <> endobj 1180 0 obj <> endobj 1192 0 obj <> endobj 1181 0 obj <> endobj 1013 0 obj <> endobj 973 0 obj <> endobj 926 0 obj <> endobj 918 0 obj <> endobj 1075 0 obj <> endobj 1056 0 obj <> endobj 1031 0 obj <> endobj 1422 0 obj <> endobj 1105 0 obj <> endobj 959 0 obj <> endobj 950 0 obj <> endobj 934 0 obj <> endobj 892 0 obj <> endobj 1356 0 obj <> endobj 1354 0 obj <> endobj 1368 0 obj <> endobj 1118 0 obj <> endobj 1109 0 obj <> endobj 782 0 obj <> endobj 767 0 obj <> endobj 772 0 obj <> endobj 1150 0 obj <> endobj 1123 0 obj <> endobj 1044 0 obj <> endobj 1033 0 obj <> endobj 1002 0 obj <> endobj 992 0 obj <> endobj 970 0 obj <> endobj 953 0 obj <> endobj 1115 0 obj <> endobj 1046 0 obj <> endobj 1041 0 obj <> endobj 1026 0 obj <> endobj 1000 0 obj <> endobj 993 0 obj <> endobj 803 0 obj <> endobj 1264 0 obj <> endobj 1223 0 obj <> endobj 1215 0 obj <> endobj 914 0 obj <> endobj 880 0 obj <> endobj 857 0 obj <> endobj 1372 0 obj <> endobj 1106 0 obj <> endobj 1087 0 obj <> endobj 1067 0 obj <> endobj 1107 0 obj <> endobj 1097 0 obj <> endobj 796 0 obj <> endobj 795 0 obj <> endobj 789 0 obj <> endobj 779 0 obj <> endobj 764 0 obj <> endobj 1232 0 obj <> endobj 886 0 obj <> endobj 790 0 obj <> endobj 1257 0 obj <> endobj 1233 0 obj <> endobj 1209 0 obj <> endobj 1186 0 obj <> endobj 1035 0 obj <> endobj 1085 0 obj <> endobj 1047 0 obj <> endobj 1016 0 obj <> endobj 1142 0 obj <> endobj 1096 0 obj <> endobj 763 0 obj <> endobj 1182 0 obj <> endobj 1161 0 obj <> endobj 1159 0 obj <> endobj 1319 0 obj <> endobj 1078 0 obj <> endobj 1068 0 obj <> endobj 1450 0 obj <> endobj 941 0 obj <> endobj 905 0 obj <> endobj 1387 0 obj <> endobj 1369 0 obj <> endobj 1069 0 obj <> endobj 1028 0 obj <> endobj 1019 0 obj <> endobj 969 0 obj <> endobj 1408 0 obj <> endobj 1400 0 obj <> endobj 1361 0 obj <> endobj 1058 0 obj <> endobj 1055 0 obj <> endobj 997 0 obj <> endobj 1426 0 obj <> endobj 1417 0 obj <> endobj 1410 0 obj <> endobj 1138 0 obj <> endobj 1130 0 obj <> endobj 1094 0 obj <> endobj 1060 0 obj <> endobj 881 0 obj <> endobj 868 0 obj <> endobj 828 0 obj <> endobj 804 0 obj <> endobj 1287 0 obj <> endobj 1241 0 obj <> endobj 1201 0 obj <> endobj 902 0 obj <> endobj 896 0 obj <> endobj 858 0 obj <> endobj 1345 0 obj <> endobj 1337 0 obj <> endobj 1253 0 obj <> endobj 998 0 obj <> endobj 944 0 obj <> endobj 917 0 obj <> endobj 916 0 obj <> endobj 1357 0 obj <> endobj 1336 0 obj <> endobj 1299 0 obj <> endobj 1054 0 obj <> endobj 999 0 obj <> endobj 966 0 obj <> endobj 964 0 obj <> endobj 1435 0 obj <> endobj 1418 0 obj <> endobj 1370 0 obj <> endobj 1362 0 obj <> endobj 1095 0 obj <> endobj 1001 0 obj <> endobj 994 0 obj <> endobj 1434 0 obj <> endobj 1407 0 obj <> endobj 849 0 obj <> endobj 1242 0 obj <> endobj 942 0 obj <> endobj 920 0 obj <> endobj 871 0 obj <> endobj 1325 0 obj <> endobj 1308 0 obj <> endobj 1252 0 obj <> endobj 984 0 obj <> endobj 1385 0 obj <> endobj 1358 0 obj <> endobj 1297 0 obj <> endobj 988 0 obj <> endobj 985 0 obj <> endobj 945 0 obj <> endobj 1414 0 obj <> endobj 1371 0 obj <> endobj 1334 0 obj <> endobj 1086 0 obj <> endobj 1018 0 obj <> endobj 989 0 obj <> endobj 986 0 obj <> endobj 832 0 obj <> endobj 785 0 obj <> endobj 783 0 obj <> endobj 1473 0 obj <> endobj 1190 0 obj <> endobj 1288 0 obj <> endobj 1285 0 obj <> endobj 1268 0 obj <> endobj 1250 0 obj <> endobj 1224 0 obj <> endobj 1200 0 obj <> endobj 1172 0 obj <> endobj 915 0 obj <> endobj 895 0 obj <> endobj 825 0 obj <> endobj 1277 0 obj <> endobj 1251 0 obj <> endobj 1227 0 obj <> endobj 1335 0 obj <> endobj 1296 0 obj <> endobj 1278 0 obj <> endobj 1014 0 obj <> endobj 946 0 obj <> endobj 1416 0 obj <> endobj 1386 0 obj <> endobj 1367 0 obj <> endobj 1359 0 obj <> endobj 1346 0 obj <> endobj 1326 0 obj <> endobj 1136 0 obj <> endobj 1133 0 obj <> endobj 1120 0 obj <> endobj 1081 0 obj <> endobj 822 0 obj <> endobj 1461 0 obj <> endobj 1455 0 obj <> endobj 1166 0 obj <> endobj 1164 0 obj <> endobj 1153 0 obj <> endobj 786 0 obj <> endobj 784 0 obj <> endobj 1266 0 obj <> endobj 1249 0 obj <> endobj 1238 0 obj <> endobj 869 0 obj <> endobj 850 0 obj <> endobj 835 0 obj <> endobj 814 0 obj <> endobj 1317 0 obj <> endobj 1298 0 obj <> endobj 1225 0 obj <> endobj 965 0 obj <> endobj 1015 0 obj <> endobj 952 0 obj <> endobj 919 0 obj <> endobj 766 0 obj <> endobj 1445 0 obj <> endobj 1421 0 obj <> endobj 922 0 obj <> endobj 1259 0 obj <> endobj 861 0 obj <> endobj 1338 0 obj <> endobj 1307 0 obj <> endobj 1197 0 obj <> endobj 990 0 obj <> endobj 1282 0 obj <> endobj 1017 0 obj <> endobj 1474 0 obj <> endobj 793 0 obj <> endobj 760 0 obj <> endobj 1339 0 obj <> endobj 1191 0 obj <> endobj 1117 0 obj <> endobj 1070 0 obj <> endobj 1032 0 obj <> endobj 977 0 obj <> endobj 1314 0 obj <> endobj 882 0 obj <> endobj 1156 0 obj <> endobj 1404 0 obj <> endobj 762 0 obj <> endobj 813 0 obj <> endobj 1457 0 obj <> endobj 1093 0 obj <> endobj 811 0 obj <> endobj 1237 0 obj <> endobj 824 0 obj <> endobj 798 0 obj <> endobj 1157 0 obj <> endobj 1135 0 obj <> endobj 769 0 obj <> endobj 1366 0 obj <> endobj 1169 0 obj <> endobj 837 0 obj <> endobj 1382 0 obj <> endobj 847 0 obj <> endobj 1342 0 obj <> endobj 1132 0 obj <> endobj 1459 0 obj <> endobj 1318 0 obj <> endobj 1088 0 obj <> endobj 904 0 obj <> endobj 768 0 obj <> endobj 967 0 obj <> endobj 1165 0 obj <> endobj 883 0 obj <> endobj 923 0 obj <> endobj 1330 0 obj <> endobj 1122 0 obj <> endobj 913 0 obj <> endobj 1218 0 obj <> endobj 1272 0 obj <> endobj 1154 0 obj <> endobj 1306 0 obj <> endobj 1440 0 obj <> endobj 956 0 obj <> endobj 1265 0 obj <> endobj 1467 0 obj <> endobj 1163 0 obj <> endobj 951 0 obj <> endobj 991 0 obj <> endobj 903 0 obj <> endobj 1134 0 obj <> endobj 1329 0 obj <> endobj 943 0 obj <> endobj 1263 0 obj <> endobj 866 0 obj <> endobj 1235 0 obj <> endobj 1454 0 obj <> endobj 1113 0 obj <> endobj 874 0 obj <> endobj 1147 0 obj <> endobj 1279 0 obj <> endobj 1458 0 obj <> endobj 1231 0 obj <> endobj 787 0 obj <> endobj 1290 0 obj <> endobj 1452 0 obj <> endobj 1108 0 obj <> endobj 1363 0 obj <> endobj 1280 0 obj <> endobj 1176 0 obj <> endobj 1021 0 obj <> endobj 1195 0 obj <> endobj 805 0 obj <> endobj 1456 0 obj <> endobj 897 0 obj <> endobj 1464 0 obj <> endobj 1217 0 obj <> endobj 1419 0 obj <> endobj 1444 0 obj <> endobj 879 0 obj <> endobj 887 0 obj <> endobj 870 0 obj <> endobj 1045 0 obj <> endobj 1194 0 obj <> endobj 893 0 obj <> endobj 947 0 obj <> endobj 1127 0 obj <> endobj xref 0 1523 0000000000 65535 f 0000177394 00000 n 0000177627 00000 n 0000123115 00000 n 0000202445 00000 n 0000216250 00000 n 0000216143 00000 n 0000213984 00000 n 0000215668 00000 n 0000216042 00000 n 0000215918 00000 n 0000215792 00000 n 0000215185 00000 n 0000215570 00000 n 0000215453 00000 n 0000215337 00000 n 0000214791 00000 n 0000215063 00000 n 0000214941 00000 n 0000214673 00000 n 0000214541 00000 n 0000214435 00000 n 0000214325 00000 n 0000214219 00000 n 0000214130 00000 n 0000208315 00000 n 0000210302 00000 n 0000210424 00000 n 0000210513 00000 n 0000209771 00000 n 0000210214 00000 n 0000210112 00000 n 0000210007 00000 n 0000209919 00000 n 0000208459 00000 n 0000208621 00000 n 0000208801 00000 n 0000208709 00000 n 0000213112 00000 n 0000213462 00000 n 0000213360 00000 n 0000213268 00000 n 0000212564 00000 n 0000212706 00000 n 0000212886 00000 n 0000212794 00000 n 0000211891 00000 n 0000212241 00000 n 0000212139 00000 n 0000212047 00000 n 0000211457 00000 n 0000211609 00000 n 0000211789 00000 n 0000211697 00000 n 0000211035 00000 n 0000211369 00000 n 0000211267 00000 n 0000211175 00000 n 0000210601 00000 n 0000210753 00000 n 0000210933 00000 n 0000210841 00000 n 0000209343 00000 n 0000209682 00000 n 0000209579 00000 n 0000209486 00000 n 0000208903 00000 n 0000209058 00000 n 0000209240 00000 n 0000209147 00000 n 0000213550 00000 n 0000213895 00000 n 0000213792 00000 n 0000213699 00000 n 0000212988 00000 n 0000212435 00000 n 0000212329 00000 n 0000203694 00000 n 0000206630 00000 n 0000205974 00000 n 0000206513 00000 n 0000206372 00000 n 0000206233 00000 n 0000206117 00000 n 0000205861 00000 n 0000205492 00000 n 0000205748 00000 n 0000205648 00000 n 0000205102 00000 n 0000205396 00000 n 0000205263 00000 n 0000204703 00000 n 0000204997 00000 n 0000204878 00000 n 0000203852 00000 n 0000204010 00000 n 0000204123 00000 n 0000204491 00000 n 0000204378 00000 n 0000204262 00000 n 0000204591 00000 n 0000207726 00000 n 0000208210 00000 n 0000208096 00000 n 0000207982 00000 n 0000207873 00000 n 0000206997 00000 n 0000207182 00000 n 0000207586 00000 n 0000207437 00000 n 0000207311 00000 n 0000206733 00000 n 0000206898 00000 n 0000202501 00000 n 0000203039 00000 n 0000202642 00000 n 0000202923 00000 n 0000202805 00000 n 0000203564 00000 n 0000203426 00000 n 0000203288 00000 n 0000203147 00000 n 0000178444 00000 n 0000000015 00000 n 0000000351 00000 n 0000178635 00000 n 0000216342 00000 n 0000216379 00000 n 0000139019 00000 n 0000123349 00000 n 0000143918 00000 n 0000178880 00000 n 0000000372 00000 n 0000003633 00000 n 0000179090 00000 n 0000145935 00000 n 0000177272 00000 n 0000179313 00000 n 0000003655 00000 n 0000005214 00000 n 0000179504 00000 n 0000179715 00000 n 0000005236 00000 n 0000017008 00000 n 0000180733 00000 n 0000140618 00000 n 0000177176 00000 n 0000177082 00000 n 0000176980 00000 n 0000176880 00000 n 0000176775 00000 n 0000176672 00000 n 0000176562 00000 n 0000176454 00000 n 0000176337 00000 n 0000176222 00000 n 0000176113 00000 n 0000176006 00000 n 0000175901 00000 n 0000175798 00000 n 0000175690 00000 n 0000175584 00000 n 0000175470 00000 n 0000175358 00000 n 0000175251 00000 n 0000175146 00000 n 0000175029 00000 n 0000174914 00000 n 0000174797 00000 n 0000174682 00000 n 0000174572 00000 n 0000174464 00000 n 0000174347 00000 n 0000174232 00000 n 0000174128 00000 n 0000174026 00000 n 0000173920 00000 n 0000173816 00000 n 0000173712 00000 n 0000173610 00000 n 0000173508 00000 n 0000173408 00000 n 0000173317 00000 n 0000173228 00000 n 0000173132 00000 n 0000173038 00000 n 0000172942 00000 n 0000172848 00000 n 0000172752 00000 n 0000172658 00000 n 0000172556 00000 n 0000172456 00000 n 0000172360 00000 n 0000172266 00000 n 0000172170 00000 n 0000172076 00000 n 0000171980 00000 n 0000171886 00000 n 0000171790 00000 n 0000171696 00000 n 0000171587 00000 n 0000171480 00000 n 0000171384 00000 n 0000171290 00000 n 0000171194 00000 n 0000171100 00000 n 0000171004 00000 n 0000170910 00000 n 0000170804 00000 n 0000170700 00000 n 0000170604 00000 n 0000170510 00000 n 0000170414 00000 n 0000170320 00000 n 0000170224 00000 n 0000170130 00000 n 0000170031 00000 n 0000169934 00000 n 0000169838 00000 n 0000169744 00000 n 0000169648 00000 n 0000169554 00000 n 0000169458 00000 n 0000169364 00000 n 0000169258 00000 n 0000169154 00000 n 0000169058 00000 n 0000168964 00000 n 0000168868 00000 n 0000168774 00000 n 0000168678 00000 n 0000168584 00000 n 0000168480 00000 n 0000168378 00000 n 0000168282 00000 n 0000168188 00000 n 0000168092 00000 n 0000167998 00000 n 0000167902 00000 n 0000167808 00000 n 0000167710 00000 n 0000167614 00000 n 0000167518 00000 n 0000167424 00000 n 0000167329 00000 n 0000167236 00000 n 0000167142 00000 n 0000167050 00000 n 0000180956 00000 n 0000017031 00000 n 0000028340 00000 n 0000182022 00000 n 0000133268 00000 n 0000166946 00000 n 0000166844 00000 n 0000166748 00000 n 0000166654 00000 n 0000166558 00000 n 0000166464 00000 n 0000166368 00000 n 0000166274 00000 n 0000166175 00000 n 0000166078 00000 n 0000165982 00000 n 0000165888 00000 n 0000165792 00000 n 0000165698 00000 n 0000165602 00000 n 0000165508 00000 n 0000165403 00000 n 0000165300 00000 n 0000165204 00000 n 0000165110 00000 n 0000165014 00000 n 0000164920 00000 n 0000164824 00000 n 0000164730 00000 n 0000164630 00000 n 0000164530 00000 n 0000164434 00000 n 0000164340 00000 n 0000164244 00000 n 0000164150 00000 n 0000164054 00000 n 0000163960 00000 n 0000163854 00000 n 0000163750 00000 n 0000163641 00000 n 0000163530 00000 n 0000163420 00000 n 0000163312 00000 n 0000163213 00000 n 0000163116 00000 n 0000163006 00000 n 0000162898 00000 n 0000162793 00000 n 0000162690 00000 n 0000162574 00000 n 0000162460 00000 n 0000162341 00000 n 0000162224 00000 n 0000162106 00000 n 0000161990 00000 n 0000161874 00000 n 0000161760 00000 n 0000161654 00000 n 0000161550 00000 n 0000161441 00000 n 0000161334 00000 n 0000161227 00000 n 0000161122 00000 n 0000161020 00000 n 0000160920 00000 n 0000160806 00000 n 0000160694 00000 n 0000160594 00000 n 0000160496 00000 n 0000160371 00000 n 0000160248 00000 n 0000160127 00000 n 0000160008 00000 n 0000159905 00000 n 0000159802 00000 n 0000159690 00000 n 0000159580 00000 n 0000159468 00000 n 0000159358 00000 n 0000159250 00000 n 0000159140 00000 n 0000159038 00000 n 0000158938 00000 n 0000158833 00000 n 0000158730 00000 n 0000158633 00000 n 0000158538 00000 n 0000158442 00000 n 0000158348 00000 n 0000158252 00000 n 0000158158 00000 n 0000158056 00000 n 0000157956 00000 n 0000157842 00000 n 0000157730 00000 n 0000157624 00000 n 0000157520 00000 n 0000157415 00000 n 0000157312 00000 n 0000157204 00000 n 0000157098 00000 n 0000156993 00000 n 0000156890 00000 n 0000156779 00000 n 0000156666 00000 n 0000156565 00000 n 0000156462 00000 n 0000156366 00000 n 0000156272 00000 n 0000156171 00000 n 0000156070 00000 n 0000155961 00000 n 0000155854 00000 n 0000182257 00000 n 0000028363 00000 n 0000029842 00000 n 0000182555 00000 n 0000155748 00000 n 0000155644 00000 n 0000155535 00000 n 0000155428 00000 n 0000155318 00000 n 0000155210 00000 n 0000155098 00000 n 0000154986 00000 n 0000154874 00000 n 0000154762 00000 n 0000154653 00000 n 0000154546 00000 n 0000182754 00000 n 0000029864 00000 n 0000030156 00000 n 0000182945 00000 n 0000183156 00000 n 0000030177 00000 n 0000033264 00000 n 0000183382 00000 n 0000135138 00000 n 0000142714 00000 n 0000154453 00000 n 0000154341 00000 n 0000154229 00000 n 0000183641 00000 n 0000033286 00000 n 0000035687 00000 n 0000183883 00000 n 0000154112 00000 n 0000153995 00000 n 0000153896 00000 n 0000153787 00000 n 0000153678 00000 n 0000184142 00000 n 0000035709 00000 n 0000038813 00000 n 0000184352 00000 n 0000153580 00000 n 0000184575 00000 n 0000038835 00000 n 0000040990 00000 n 0000184766 00000 n 0000185025 00000 n 0000041012 00000 n 0000043310 00000 n 0000185235 00000 n 0000153478 00000 n 0000185494 00000 n 0000043332 00000 n 0000044885 00000 n 0000185685 00000 n 0000185932 00000 n 0000044907 00000 n 0000047954 00000 n 0000186166 00000 n 0000153367 00000 n 0000153260 00000 n 0000153150 00000 n 0000153040 00000 n 0000186425 00000 n 0000047976 00000 n 0000050952 00000 n 0000186643 00000 n 0000152936 00000 n 0000152830 00000 n 0000186914 00000 n 0000050974 00000 n 0000053581 00000 n 0000187105 00000 n 0000187376 00000 n 0000053603 00000 n 0000054759 00000 n 0000187567 00000 n 0000187814 00000 n 0000054781 00000 n 0000055092 00000 n 0000188005 00000 n 0000188216 00000 n 0000055113 00000 n 0000057511 00000 n 0000188434 00000 n 0000137697 00000 n 0000152720 00000 n 0000152610 00000 n 0000188693 00000 n 0000057533 00000 n 0000059936 00000 n 0000188884 00000 n 0000136757 00000 n 0000189167 00000 n 0000059958 00000 n 0000062196 00000 n 0000189377 00000 n 0000152496 00000 n 0000189636 00000 n 0000062218 00000 n 0000064628 00000 n 0000189854 00000 n 0000152396 00000 n 0000152294 00000 n 0000190113 00000 n 0000064650 00000 n 0000066823 00000 n 0000190304 00000 n 0000190563 00000 n 0000066845 00000 n 0000068552 00000 n 0000190754 00000 n 0000191013 00000 n 0000068574 00000 n 0000071002 00000 n 0000191231 00000 n 0000152190 00000 n 0000152084 00000 n 0000191490 00000 n 0000071024 00000 n 0000073891 00000 n 0000191716 00000 n 0000151976 00000 n 0000151868 00000 n 0000151764 00000 n 0000191963 00000 n 0000073913 00000 n 0000076237 00000 n 0000192181 00000 n 0000151660 00000 n 0000151545 00000 n 0000192440 00000 n 0000076259 00000 n 0000078505 00000 n 0000192658 00000 n 0000151441 00000 n 0000151337 00000 n 0000192917 00000 n 0000078527 00000 n 0000080408 00000 n 0000193127 00000 n 0000151236 00000 n 0000193374 00000 n 0000080430 00000 n 0000080729 00000 n 0000193565 00000 n 0000193776 00000 n 0000080750 00000 n 0000082592 00000 n 0000193967 00000 n 0000194226 00000 n 0000082614 00000 n 0000085212 00000 n 0000194436 00000 n 0000151137 00000 n 0000194707 00000 n 0000085234 00000 n 0000087625 00000 n 0000194898 00000 n 0000195145 00000 n 0000087647 00000 n 0000089487 00000 n 0000195355 00000 n 0000151033 00000 n 0000195602 00000 n 0000089509 00000 n 0000091859 00000 n 0000195820 00000 n 0000150915 00000 n 0000150813 00000 n 0000196079 00000 n 0000091881 00000 n 0000093254 00000 n 0000196270 00000 n 0000196517 00000 n 0000093276 00000 n 0000095834 00000 n 0000196743 00000 n 0000150707 00000 n 0000150603 00000 n 0000150497 00000 n 0000197002 00000 n 0000095856 00000 n 0000098486 00000 n 0000197193 00000 n 0000197452 00000 n 0000098508 00000 n 0000100691 00000 n 0000197643 00000 n 0000197902 00000 n 0000100713 00000 n 0000102703 00000 n 0000198093 00000 n 0000198352 00000 n 0000102725 00000 n 0000104700 00000 n 0000198543 00000 n 0000141954 00000 n 0000198802 00000 n 0000104722 00000 n 0000105018 00000 n 0000198993 00000 n 0000199204 00000 n 0000105039 00000 n 0000108383 00000 n 0000199430 00000 n 0000150306 00000 n 0000150115 00000 n 0000149929 00000 n 0000199677 00000 n 0000108405 00000 n 0000110790 00000 n 0000199887 00000 n 0000149747 00000 n 0000200122 00000 n 0000110812 00000 n 0000113349 00000 n 0000200404 00000 n 0000149561 00000 n 0000149370 00000 n 0000149182 00000 n 0000148987 00000 n 0000148797 00000 n 0000148606 00000 n 0000148418 00000 n 0000148226 00000 n 0000148039 00000 n 0000147852 00000 n 0000200651 00000 n 0000113371 00000 n 0000116876 00000 n 0000200893 00000 n 0000147664 00000 n 0000147557 00000 n 0000147451 00000 n 0000147259 00000 n 0000147067 00000 n 0000201128 00000 n 0000116898 00000 n 0000119601 00000 n 0000201319 00000 n 0000201566 00000 n 0000119623 00000 n 0000122519 00000 n 0000201784 00000 n 0000146871 00000 n 0000146772 00000 n 0000202031 00000 n 0000122541 00000 n 0000123094 00000 n 0000202222 00000 n 0000130448 00000 n 0000130470 00000 n 0000130555 00000 n 0000130594 00000 n 0000133782 00000 n 0000134288 00000 n 0000134478 00000 n 0000135117 00000 n 0000135607 00000 n 0000135984 00000 n 0000136185 00000 n 0000136736 00000 n 0000137001 00000 n 0000137105 00000 n 0000137314 00000 n 0000137676 00000 n 0000138119 00000 n 0000138333 00000 n 0000138533 00000 n 0000138998 00000 n 0000139494 00000 n 0000139816 00000 n 0000140021 00000 n 0000140597 00000 n 0000141033 00000 n 0000141279 00000 n 0000141479 00000 n 0000141933 00000 n 0000142123 00000 n 0000142181 00000 n 0000142381 00000 n 0000142693 00000 n 0000143113 00000 n 0000143275 00000 n 0000143476 00000 n 0000143897 00000 n 0000144536 00000 n 0000145064 00000 n 0000145260 00000 n 0000145914 00000 n 0000146121 00000 n 0000146220 00000 n 0000146416 00000 n 0000146751 00000 n 0000177718 00000 n 0000177865 00000 n 0000178012 00000 n 0000178159 00000 n 0000178306 00000 n 0000178748 00000 n 0000178860 00000 n 0000179181 00000 n 0000179293 00000 n 0000179583 00000 n 0000179695 00000 n 0000180824 00000 n 0000180936 00000 n 0000182125 00000 n 0000182237 00000 n 0000182622 00000 n 0000182734 00000 n 0000183024 00000 n 0000183136 00000 n 0000183509 00000 n 0000183621 00000 n 0000184010 00000 n 0000184122 00000 n 0000184443 00000 n 0000184555 00000 n 0000184893 00000 n 0000185005 00000 n 0000185362 00000 n 0000185474 00000 n 0000185800 00000 n 0000185912 00000 n 0000186293 00000 n 0000186405 00000 n 0000186782 00000 n 0000186894 00000 n 0000187244 00000 n 0000187356 00000 n 0000187682 00000 n 0000187794 00000 n 0000188084 00000 n 0000188196 00000 n 0000188561 00000 n 0000188673 00000 n 0000189035 00000 n 0000189147 00000 n 0000189504 00000 n 0000189616 00000 n 0000189981 00000 n 0000190093 00000 n 0000190431 00000 n 0000190543 00000 n 0000190881 00000 n 0000190993 00000 n 0000191358 00000 n 0000191470 00000 n 0000191831 00000 n 0000191943 00000 n 0000192308 00000 n 0000192420 00000 n 0000192785 00000 n 0000192897 00000 n 0000193242 00000 n 0000193354 00000 n 0000193644 00000 n 0000193756 00000 n 0000194094 00000 n 0000194206 00000 n 0000194575 00000 n 0000194687 00000 n 0000195013 00000 n 0000195125 00000 n 0000195470 00000 n 0000195582 00000 n 0000195947 00000 n 0000196059 00000 n 0000196385 00000 n 0000196497 00000 n 0000196870 00000 n 0000196982 00000 n 0000197320 00000 n 0000197432 00000 n 0000197770 00000 n 0000197882 00000 n 0000198220 00000 n 0000198332 00000 n 0000198670 00000 n 0000198782 00000 n 0000199072 00000 n 0000199184 00000 n 0000199545 00000 n 0000199657 00000 n 0000199990 00000 n 0000200102 00000 n 0000200519 00000 n 0000200631 00000 n 0000200996 00000 n 0000201108 00000 n 0000201434 00000 n 0000201546 00000 n 0000201899 00000 n 0000202011 00000 n 0000202313 00000 n 0000202425 00000 n 0000273501 00000 n 0000242716 00000 n 0000274073 00000 n 0000265476 00000 n 0000264737 00000 n 0000255189 00000 n 0000272764 00000 n 0000263008 00000 n 0000275241 00000 n 0000274601 00000 n 0000243075 00000 n 0000241823 00000 n 0000263060 00000 n 0000253562 00000 n 0000243652 00000 n 0000248997 00000 n 0000248264 00000 n 0000241042 00000 n 0000256284 00000 n 0000264685 00000 n 0000246537 00000 n 0000241773 00000 n 0000262956 00000 n 0000269984 00000 n 0000271979 00000 n 0000269932 00000 n 0000271929 00000 n 0000276986 00000 n 0000246589 00000 n 0000264633 00000 n 0000264894 00000 n 0000256494 00000 n 0000256599 00000 n 0000273449 00000 n 0000248212 00000 n 0000264581 00000 n 0000264529 00000 n 0000246485 00000 n 0000274440 00000 n 0000253510 00000 n 0000255501 00000 n 0000253458 00000 n 0000255449 00000 n 0000263848 00000 n 0000267162 00000 n 0000277465 00000 n 0000240885 00000 n 0000248162 00000 n 0000241458 00000 n 0000248419 00000 n 0000261008 00000 n 0000274284 00000 n 0000241094 00000 n 0000274125 00000 n 0000272346 00000 n 0000248110 00000 n 0000248058 00000 n 0000260955 00000 n 0000247375 00000 n 0000242973 00000 n 0000261380 00000 n 0000250676 00000 n 0000271614 00000 n 0000260902 00000 n 0000274389 00000 n 0000270613 00000 n 0000257177 00000 n 0000259273 00000 n 0000267110 00000 n 0000256651 00000 n 0000244543 00000 n 0000260849 00000 n 0000269880 00000 n 0000255866 00000 n 0000240937 00000 n 0000272294 00000 n 0000258123 00000 n 0000274758 00000 n 0000243390 00000 n 0000244490 00000 n 0000244915 00000 n 0000255137 00000 n 0000244439 00000 n 0000260796 00000 n 0000254136 00000 n 0000260743 00000 n 0000250624 00000 n 0000274865 00000 n 0000259585 00000 n 0000268724 00000 n 0000272242 00000 n 0000243285 00000 n 0000241146 00000 n 0000244386 00000 n 0000253406 00000 n 0000255814 00000 n 0000242349 00000 n 0000264161 00000 n 0000267475 00000 n 0000260269 00000 n 0000259067 00000 n 0000273027 00000 n 0000244333 00000 n 0000259376 00000 n 0000244280 00000 n 0000252249 00000 n 0000276505 00000 n 0000255762 00000 n 0000267058 00000 n 0000272190 00000 n 0000277945 00000 n 0000268933 00000 n 0000242868 00000 n 0000259637 00000 n 0000276719 00000 n 0000258334 00000 n 0000257912 00000 n 0000247688 00000 n 0000250989 00000 n 0000277839 00000 n 0000264109 00000 n 0000267006 00000 n 0000273919 00000 n 0000275399 00000 n 0000261328 00000 n 0000250572 00000 n 0000264842 00000 n 0000277892 00000 n 0000255710 00000 n 0000258386 00000 n 0000252458 00000 n 0000243600 00000 n 0000262641 00000 n 0000278106 00000 n 0000243180 00000 n 0000270561 00000 n 0000267425 00000 n 0000277572 00000 n 0000261276 00000 n 0000247636 00000 n 0000250520 00000 n 0000243025 00000 n 0000267373 00000 n 0000276242 00000 n 0000275188 00000 n 0000265951 00000 n 0000244863 00000 n 0000248367 00000 n 0000259901 00000 n 0000246170 00000 n 0000254084 00000 n 0000242611 00000 n 0000250937 00000 n 0000275609 00000 n 0000264057 00000 n 0000270509 00000 n 0000267842 00000 n 0000267790 00000 n 0000262172 00000 n 0000272712 00000 n 0000268881 00000 n 0000244811 00000 n 0000272922 00000 n 0000275450 00000 n 0000250885 00000 n 0000249468 00000 n 0000262120 00000 n 0000243757 00000 n 0000258962 00000 n 0000258858 00000 n 0000242087 00000 n 0000247586 00000 n 0000254032 00000 n 0000251355 00000 n 0000262591 00000 n 0000251303 00000 n 0000245705 00000 n 0000241198 00000 n 0000252406 00000 n 0000257072 00000 n 0000256232 00000 n 0000265899 00000 n 0000268829 00000 n 0000276400 00000 n 0000267738 00000 n 0000269459 00000 n 0000271034 00000 n 0000278158 00000 n 0000245653 00000 n 0000257020 00000 n 0000262541 00000 n 0000276138 00000 n 0000272660 00000 n 0000263481 00000 n 0000257754 00000 n 0000246118 00000 n 0000275927 00000 n 0000249416 00000 n 0000252354 00000 n 0000262489 00000 n 0000256442 00000 n 0000251251 00000 n 0000252985 00000 n 0000254555 00000 n 0000268210 00000 n 0000272555 00000 n 0000268158 00000 n 0000275294 00000 n 0000257651 00000 n 0000266268 00000 n 0000263429 00000 n 0000256915 00000 n 0000246068 00000 n 0000262068 00000 n 0000256180 00000 n 0000259689 00000 n 0000247007 00000 n 0000273816 00000 n 0000246018 00000 n 0000258910 00000 n 0000256075 00000 n 0000251722 00000 n 0000251672 00000 n 0000259119 00000 n 0000269144 00000 n 0000269407 00000 n 0000269828 00000 n 0000249785 00000 n 0000269355 00000 n 0000269776 00000 n 0000273238 00000 n 0000276190 00000 n 0000263377 00000 n 0000263796 00000 n 0000268570 00000 n 0000246955 00000 n 0000245601 00000 n 0000266585 00000 n 0000267686 00000 n 0000268106 00000 n 0000263743 00000 n 0000268517 00000 n 0000263324 00000 n 0000252667 00000 n 0000252932 00000 n 0000242034 00000 n 0000252879 00000 n 0000253353 00000 n 0000258228 00000 n 0000253300 00000 n 0000246904 00000 n 0000247322 00000 n 0000252090 00000 n 0000262015 00000 n 0000270981 00000 n 0000272607 00000 n 0000265317 00000 n 0000273343 00000 n 0000269723 00000 n 0000266215 00000 n 0000260057 00000 n 0000277357 00000 n 0000260321 00000 n 0000250100 00000 n 0000251198 00000 n 0000251619 00000 n 0000263690 00000 n 0000252037 00000 n 0000266162 00000 n 0000247271 00000 n 0000257703 00000 n 0000262330 00000 n 0000273763 00000 n 0000263271 00000 n 0000246851 00000 n 0000265158 00000 n 0000243809 00000 n 0000254502 00000 n 0000245548 00000 n 0000256127 00000 n 0000248840 00000 n 0000263637 00000 n 0000253247 00000 n 0000249732 00000 n 0000263218 00000 n 0000277998 00000 n 0000263584 00000 n 0000265264 00000 n 0000247218 00000 n 0000245861 00000 n 0000249679 00000 n 0000246798 00000 n 0000248681 00000 n 0000258754 00000 n 0000268053 00000 n 0000266532 00000 n 0000262277 00000 n 0000242766 00000 n 0000266479 00000 n 0000260110 00000 n 0000266953 00000 n 0000258489 00000 n 0000247165 00000 n 0000260216 00000 n 0000246745 00000 n 0000247112 00000 n 0000248787 00000 n 0000264370 00000 n 0000265793 00000 n 0000266109 00000 n 0000273710 00000 n 0000251566 00000 n 0000250047 00000 n 0000245810 00000 n 0000249994 00000 n 0000262224 00000 n 0000250467 00000 n 0000241614 00000 n 0000265740 00000 n 0000243494 00000 n 0000259169 00000 n 0000271561 00000 n 0000247899 00000 n 0000249312 00000 n 0000249626 00000 n 0000265211 00000 n 0000269670 00000 n 0000264317 00000 n 0000275134 00000 n 0000258281 00000 n 0000259220 00000 n 0000245757 00000 n 0000249259 00000 n 0000274230 00000 n 0000266900 00000 n 0000268466 00000 n 0000265423 00000 n 0000264476 00000 n 0000255084 00000 n 0000242454 00000 n 0000248734 00000 n 0000241928 00000 n 0000253194 00000 n 0000242245 00000 n 0000247846 00000 n 0000262436 00000 n 0000264264 00000 n 0000264423 00000 n 0000277147 00000 n 0000262903 00000 n 0000250414 00000 n 0000251984 00000 n 0000248944 00000 n 0000276665 00000 n 0000248005 00000 n 0000263533 00000 n 0000257335 00000 n 0000273657 00000 n 0000262850 00000 n 0000243443 00000 n 0000271508 00000 n 0000245965 00000 n 0000275555 00000 n 0000263165 00000 n 0000247793 00000 n 0000256756 00000 n 0000247952 00000 n 0000278210 00000 n 0000246432 00000 n 0000260639 00000 n 0000266847 00000 n 0000259532 00000 n 0000274972 00000 n 0000271455 00000 n 0000276294 00000 n 0000274547 00000 n 0000271404 00000 n 0000247059 00000 n 0000266794 00000 n 0000246379 00000 n 0000243915 00000 n 0000240989 00000 n 0000265370 00000 n 0000255031 00000 n 0000246694 00000 n 0000257494 00000 n 0000242663 00000 n 0000276772 00000 n 0000244176 00000 n 0000250361 00000 n 0000263112 00000 n 0000254978 00000 n 0000254925 00000 n 0000271876 00000 n 0000275770 00000 n 0000250308 00000 n 0000273971 00000 n 0000274493 00000 n 0000248893 00000 n 0000265634 00000 n 0000260690 00000 n 0000265581 00000 n 0000261644 00000 n 0000276085 00000 n 0000271823 00000 n 0000275345 00000 n 0000271770 00000 n 0000246641 00000 n 0000258648 00000 n 0000274706 00000 n 0000255396 00000 n 0000241563 00000 n 0000270458 00000 n 0000259428 00000 n 0000249153 00000 n 0000243968 00000 n 0000277305 00000 n 0000244229 00000 n 0000259325 00000 n 0000249100 00000 n 0000261856 00000 n 0000261962 00000 n 0000265528 00000 n 0000245177 00000 n 0000261591 00000 n 0000255343 00000 n 0000265105 00000 n 0000256967 00000 n 0000255290 00000 n 0000258070 00000 n 0000270089 00000 n 0000273604 00000 n 0000261909 00000 n 0000257859 00000 n 0000278052 00000 n 0000277411 00000 n 0000253981 00000 n 0000273185 00000 n 0000261538 00000 n 0000261485 00000 n 0000270405 00000 n 0000267320 00000 n 0000245389 00000 n 0000245495 00000 n 0000257964 00000 n 0000249049 00000 n 0000245126 00000 n 0000242558 00000 n 0000248628 00000 n 0000265052 00000 n 0000253614 00000 n 0000259794 00000 n 0000256546 00000 n 0000245442 00000 n 0000241405 00000 n 0000264004 00000 n 0000261803 00000 n 0000277677 00000 n 0000275662 00000 n 0000245073 00000 n 0000245020 00000 n 0000253928 00000 n 0000250832 00000 n 0000263951 00000 n 0000270352 00000 n 0000272502 00000 n 0000260427 00000 n 0000270769 00000 n 0000248575 00000 n 0000256703 00000 n 0000259479 00000 n 0000276934 00000 n 0000264789 00000 n 0000264999 00000 n 0000261432 00000 n 0000276557 00000 n 0000247533 00000 n 0000274335 00000 n 0000272137 00000 n 0000245336 00000 n 0000258438 00000 n 0000267267 00000 n 0000268776 00000 n 0000247480 00000 n 0000253875 00000 n 0000256022 00000 n 0000243127 00000 n 0000254292 00000 n 0000256862 00000 n 0000272084 00000 n 0000270299 00000 n 0000270716 00000 n 0000269091 00000 n 0000267633 00000 n 0000248314 00000 n 0000248522 00000 n 0000244967 00000 n 0000264946 00000 n 0000243704 00000 n 0000272974 00000 n 0000255657 00000 n 0000250779 00000 n 0000252301 00000 n 0000276452 00000 n 0000263900 00000 n 0000275979 00000 n 0000272031 00000 n 0000241720 00000 n 0000270246 00000 n 0000243547 00000 n 0000242507 00000 n 0000255604 00000 n 0000275716 00000 n 0000253822 00000 n 0000252614 00000 n 0000254239 00000 n 0000251145 00000 n 0000270663 00000 n 0000270928 00000 n 0000276826 00000 n 0000277253 00000 n 0000248469 00000 n 0000273290 00000 n 0000247427 00000 n 0000255553 00000 n 0000270193 00000 n 0000253771 00000 n 0000267214 00000 n 0000270140 00000 n 0000242401 00000 n 0000277039 00000 n 0000258175 00000 n 0000261169 00000 n 0000254186 00000 n 0000254449 00000 n 0000260586 00000 n 0000270875 00000 n 0000269302 00000 n 0000272449 00000 n 0000268000 00000 n 0000260163 00000 n 0000253718 00000 n 0000250726 00000 n 0000261115 00000 n 0000253665 00000 n 0000261061 00000 n 0000275821 00000 n 0000273132 00000 n 0000269038 00000 n 0000244704 00000 n 0000257547 00000 n 0000244125 00000 n 0000254396 00000 n 0000252826 00000 n 0000273866 00000 n 0000255969 00000 n 0000251513 00000 n 0000272398 00000 n 0000275080 00000 n 0000265687 00000 n 0000244650 00000 n 0000241875 00000 n 0000244596 00000 n 0000252561 00000 n 0000260533 00000 n 0000268985 00000 n 0000271351 00000 n 0000242298 00000 n 0000242192 00000 n 0000276347 00000 n 0000275503 00000 n 0000240781 00000 n 0000255918 00000 n 0000249206 00000 n 0000269617 00000 n 0000270822 00000 n 0000267947 00000 n 0000267580 00000 n 0000273079 00000 n 0000273551 00000 n 0000244074 00000 n 0000252510 00000 n 0000274918 00000 n 0000254872 00000 n 0000259741 00000 n 0000267527 00000 n 0000271298 00000 n 0000243232 00000 n 0000241667 00000 n 0000253143 00000 n 0000254343 00000 n 0000260480 00000 n 0000251460 00000 n 0000251092 00000 n 0000262744 00000 n 0000257229 00000 n 0000262691 00000 n 0000267894 00000 n 0000269249 00000 n 0000271245 00000 n 0000257124 00000 n 0000266426 00000 n 0000268415 00000 n 0000277201 00000 n 0000251039 00000 n 0000254819 00000 n 0000274654 00000 n 0000271192 00000 n 0000262797 00000 n 0000266056 00000 n 0000268362 00000 n 0000269564 00000 n 0000264211 00000 n 0000244021 00000 n 0000257388 00000 n 0000246273 00000 n 0000241301 00000 n 0000246220 00000 n 0000251407 00000 n 0000252773 00000 n 0000254766 00000 n 0000259847 00000 n 0000274811 00000 n 0000249941 00000 n 0000251931 00000 n 0000269196 00000 n 0000271139 00000 n 0000266003 00000 n 0000240728 00000 n 0000241352 00000 n 0000246326 00000 n 0000254713 00000 n 0000257600 00000 n 0000249573 00000 n 0000259951 00000 n 0000251878 00000 n 0000253090 00000 n 0000241981 00000 n 0000247740 00000 n 0000260004 00000 n 0000266373 00000 n 0000241250 00000 n 0000252720 00000 n 0000254660 00000 n 0000274022 00000 n 0000249520 00000 n 0000258017 00000 n 0000268673 00000 n 0000266320 00000 n 0000241510 00000 n 0000266741 00000 n 0000256809 00000 n 0000242139 00000 n 0000249888 00000 n 0000269511 00000 n 0000257806 00000 n 0000271086 00000 n 0000266688 00000 n 0000268311 00000 n 0000277731 00000 n 0000261223 00000 n 0000272869 00000 n 0000262383 00000 n 0000252196 00000 n 0000249837 00000 n 0000250255 00000 n 0000266637 00000 n 0000253037 00000 n 0000254607 00000 n 0000250204 00000 n 0000251825 00000 n 0000243862 00000 n 0000258595 00000 n 0000244758 00000 n 0000268622 00000 n 0000268260 00000 n 0000260374 00000 n 0000257441 00000 n 0000256389 00000 n 0000245912 00000 n 0000275874 00000 n 0000240832 00000 n 0000250151 00000 n 0000242817 00000 n 0000277785 00000 n 0000272816 00000 n 0000252143 00000 n 0000251772 00000 n 0000261750 00000 n 0000243337 00000 n 0000265846 00000 n 0000261697 00000 n 0000277093 00000 n 0000258701 00000 n 0000276611 00000 n 0000271719 00000 n 0000277518 00000 n 0000274177 00000 n 0000276880 00000 n 0000275026 00000 n 0000256336 00000 n 0000271666 00000 n 0000245283 00000 n 0000259014 00000 n 0000277623 00000 n 0000249365 00000 n 0000245230 00000 n 0000276032 00000 n 0000257282 00000 n 0000258542 00000 n 0000258807 00000 n 0000242920 00000 n 0000255239 00000 n 0000270036 00000 n 0000273396 00000 n 0000216437 00000 n 0000223500 00000 n 0000232510 00000 n 0000216640 00000 n 0000217121 00000 n 0000217762 00000 n 0000218400 00000 n 0000218927 00000 n 0000219305 00000 n 0000219687 00000 n 0000220067 00000 n 0000220449 00000 n 0000220828 00000 n 0000221210 00000 n 0000221593 00000 n 0000221975 00000 n 0000222355 00000 n 0000222736 00000 n 0000223120 00000 n 0000223716 00000 n 0000224100 00000 n 0000224480 00000 n 0000224894 00000 n 0000225504 00000 n 0000226195 00000 n 0000226989 00000 n 0000227675 00000 n 0000228314 00000 n 0000228837 00000 n 0000229363 00000 n 0000229887 00000 n 0000230409 00000 n 0000230932 00000 n 0000231461 00000 n 0000231987 00000 n 0000232708 00000 n 0000233231 00000 n 0000233755 00000 n 0000234277 00000 n 0000234804 00000 n 0000235332 00000 n 0000235855 00000 n 0000236494 00000 n 0000237166 00000 n 0000238010 00000 n 0000238889 00000 n 0000239451 00000 n 0000240198 00000 n trailer <<936EC2CE1C090A095B718810C107F76C>] >> startxref 278263 %%EOF qmtest-2.4.1/doc/0000775000076400007640000000000011122067201013124 5ustar stefanstefanqmtest-2.4.1/doc/customizing.xml0000664000076400007640000012237411110103716016231 0ustar stefanstefan %entities; ]> Customizing <application>QMTest</application> The previous chapter introduced the concepts underlying QMTest's design. These were demonstrated with particular types of tests, resources, databases, etc. . These types are designed to be extensible, i.e. QMTest can operate with arbitrary instances of these types. In fact, QMTest provides a large number of such extensions. This chapter discusses how to use them, i.e. how to find out what extensions are available, and how to use them to construct custom test databases.
Extensions In the previous chapter we have created a test database containing a number of tests. These tests were instances of test types, such as python.ExecTest. When creating a test, a user chooses a test type, and assigns test-specific parameters to it. The same extension mechanism is used for other aspects of QMTest's functionality. All these types are extensions, which provide a generic interface for QMTest to query. To find out what extensions are available, use qmtest extensions. To list all available test types, use: > qmtest extensions -k test ** Available test classes ** - command.ExecTest Check a program's output and exit code. - command.ShellCommandTest Check a shell command's output and exit code. - python.ExecTest Check that a Python expression evaluates to true. ... To find out more about a particular extension type, use the describe command: > qmtest describe test command.ExecTest class name: python.ExecTest Check that a Python expression evaluates to true. class attributes: prerequisites The tests on which this test depends. source The source code. target_group The targets on which this test can run. expression The expression to evaluate. resources Resources on which this test or resource depends. To create a test of that type, you can call: > qmtest create --id=my_test -a expression='True' test python.ExecTest where the extension parameters are specified with the option. QMTest searches for extensions in particular places, in the following order: in the paths contained in the QMTEST_CLASS_PATH environment variable. in the class-path associated with a particular test database (typically the QMTest/ subdirectory). in the site-extension path associated with a particular QMTest installation. in the set of built-in extensions that come with a particular QMTest installation. This search allows users to provide their own extension types. See for a detailed discussion of how to create new extensions. The rest of this chapter will discuss the various extension kinds that can be used to customize QMTest.
Tests
<classname>command.ExecTest</classname> The command.ExecTest test class runs a program from an ordinary executable file. Each test specifies the program executable to run, its full command line, and the data to feed to its standard input stream. ExecTest collects the complete text of the program's standard output and standard error streams and the program's exit code, and compares these to expected values specified in the test. If the standard output and error text and the exit code match the expected values, the test passes. A command.ExecTest test supplies the following arguments: Program (text field) The name of the executable file to run. command.ExecTest attempts to locate the program executable in the path specified by the path property of the test context. Argument List (set of strings) The argument list for the program. The elements of this set are sequential items from which the program's argument list is constructed. command.ExecTest automatically prepends an implicit zeroth element, the full path of the program. Standard Input (text field) Text or data to pass to the program's standard input stream. This data is written to a temporary file, and the contents of the file are directed to the program's standard input stream. Environment (set of strings) The environment (i.e. the set of environment variables) available to the executing program. Each element of this argument is a string of the form "VARIABLE=VALUE". command.ExecTest adds additional environment variables automatically. In addition, every context property whose value is a string is accessible as an environment variable; the name of the environment variable is the name of the context property, prefixed with "QMV_" and with any dots (".") replaced by a double underscore ("__"). For example, the value of the context property "CompilerTable.c_path" is available as the value of the environment variable "QMV_CompilerTable__c_path". Expected Exit Code (integer field) The exit code value expected from the program. If the program produces an exit code value different from this one, the test fails. Expected Standard Output (text field) The text or data which the program is expected to produce on its standard output stream. The actual text or data written to standard output is captured, and command.ExecTest performs a bytewise comparison to the expected text or data. If they do not match, the test fails. Expected Standard Error (text field) The text or data which the program is expected to produce on its standard error stream. The actual text or data written to standard error is captured, and command.ExecTest performs a bytewise comparison to the expected text or data. If they do not match, the test fails.
<classname>command.ShellCommandTest</classname> command.ShellCommandTest is very similar to command.ExecTest, except that it runs a program via the shell rather than directly. Instead of specifying an executable to run and the elements of its argument list, a test provides a single command line. The shell is responsible for finding the executable and constructing its argument list. Standard input and the environment are specified in the test. The test passes if the command produces the expected standard output, standard error, and exit code. Note that most shells create local shell variables to mirror the contents of the environment when the shell starts up. Therefore, the environment set up by a command.ShellCommandTest, including the contents of the test context, are directly accessible via shell variables. The syntax to use depends on the particular shell. command.ShellCommandTest has the same fields as command.ExecTest, except that the Program and Argument List properties are replaced with these: Command (text field) The command to run. The command is delivered verbatim to the shell. The shell interprets the command according to its own quoting rules and syntax.
<classname>command.ShellScriptTest</classname> command.ShellScriptTest is an extension of command.CommandTest that lets a test specify an entire shell script instead of a single command. The script specified in the test is written to a temporary file, and this file is interpreted by the specified shell or command interpreter program. Standard input, the environment, and the argument list to pass to the script are specified in the test. The test passes if the script produces the expected standard output, standard error, and exit code. Note that most shells create local shell variables to mirror the contents of the environment when the shell starts up. Therefore, the environment set up by a command.ShellScriptTest, including the contents of the test context, are directly accessible via shell variables. The syntax to use depends on the particular shell. command.ShellScriptTest has the same fields as command.ExecTest, except that the Program property is replaced with: Script (text field) The text of the script to run.
<classname>CompilationTest</classname> compilation_test.CompilationTest compiles a set of source files and optionally runs the compiled executable. The compiler executable's name, as well as global compilation parameters are queried from these context variables: CompilationTest.compiler_path The name of the compiler executable. CompilationTest.compiler_options Compiler options. CompilationTest.compiler_ldflags Linker options. The CompilationTest takes the following parameters. options (set field) Test-specific options to pass to the compiler. ldflags (set field) Test-specific linker flags to pass to the compiler. source_files (set field) Source files to be compiled.. executable (text field) The name of the executable to be compiled. execute (boolean field) Whether or not to run the compiled executable.
Test Suites
Test Resources
<classname>TempDirectoryResource</classname> An instance of this resource creates a temporary directory during setup, and deletes it during cleanup. The full path to the directory is available to tests via a context property. dir_path_property (text field) The name of the context property which is set to the path to the temporary directory.
<classname>CompilerTable</classname> A CompilerTable resource creates a set of compiler objects according to context variables. These compiler objects are then made available to test instances through the compilers context variable that maps language names to compiler objects. The context variable CompilerTable.languages should be a whitespace-separated list of programming language names. Then, for each language <lang>, the following variables are looked up and used for the creation of compiler objects: CompilerTable.<lang>_kind (text field) The kind of compiler (e.g., "GCC" or "EDG"). CompilerTable.<lang>_path (text field) The path to the compiler. CompilerTable.<lang>_options (text field) A whitespace-separated list of command-line options to provide to the compiler.
Test Databases
XMLDatabase The XMLDatabase stores its content as a directory hierarchy containing XML files. It is the default test database used by QMTest. Each QMTest subdirectory is represented by a subdirectory in the filesystem. A test, suite, or resource is represented by an XML file. These files have file extensions .qmt, .qms, and .qma, respectively. Expert QMTest users may modify the contents of the test database directly by editing these files. However, it is the user's responsibility to ensure the integrity and validity of the XML contents of each file. For example, file and directory names should contain only characters allowed in identifiers (lower-case letters, digits, hyphens, and underscores); a period should only be used before a file extension, such as .qmt. Also, the files and directories in a test database should not be modified directly while QMTest is running with that test database.
<classname>CompilationTestDatabase</classname> The CompilationTestDatabase associates source files with CompilationTest instances. The mapping uses file extensions to determine the programming language, and thus, what compiler and compilation flags to use. To create a new test, simply add a source file with an appropriate file extension to the test database. All tests use the CompilerTable resource, and therefor require the appropriate context variables to be provided. Additionally, more compiler options can be added per test id or even subdirectory id. Given the following context file: CompilerTable.languages=c CompilerTable.c_kind=GCC CompilerTable.c_path=gcc CompilerTable.c_options=-O2 a.b.c_options=-I /a/b/common a.b.c.c_options=-I /a/b/c a test a/b/c/test.c will be compiled with gcc -O2 -I /a/b/common -I /a/b/c while a test a/b/d/test.c will be compiled with gcc -O2 -I /a/b/common. The CompilationTestDatabase takes the following parameters. srcdir (text field) The root of the test suite's source tree. excluded_subdirs (set field) A set of directory names not to be parsed as subdirectories. test_extensions (dictionary field) The mapping from file extensions to programming languages.
Expectation Databases
PreviousTestRun The PreviousTestRun queries expectations from a results file. Thus, running QMTest twice, the second time using the results of the first test run as expectations, will result in no unexpected results: > qmtest run -o my_results.qmr --- TEST RESULTS ------------------------------------------------------------- exec0 : PASS exec1 : FAIL ... exec2 : PASS --- TESTS THAT DID NOT PASS -------------------------------------------------- exec1 : FAIL Expression evaluates to false. --- STATISTICS --------------------------------------------------------------- 3 tests total 1 ( 33%) tests FAIL 2 ( 67%) tests PASS > qmtest run -e previous_testrun.PreviousTestRun(file_name="my_results.qmr") --- TEST RESULTS ------------------------------------------------------------- exec0 : PASS exec1 : XFAIL ... exec2 : PASS --- TESTS WITH UNEXPECTED OUTCOMES ------------------------------------------- None. --- STATISTICS --------------------------------------------------------------- 3 (100%) tests as expected Since taking previous test runs as expectations is a common use case, the second command above may be expressed in a more compact form as: qmtest run -O my_results.qmr The PreviousTestRun takes the following parameters. file_name (text field) The filename of the results file.
XMLExpectationDatabase The XMLExpectationDatabase stores expectations in an XML file. Instead of containing expectations for all tests, individual expectations are computed from rules by matching test-ids as well as test-run annotations against specific rules. ]]> The above little expectation database thus contains the following rules (subsequent matching rules override previous matching rules): All tests are expected to fail if the annotation a has value b. All tests whose test-ids start with first are expected to fail. The XMLExpectationDatabase takes the following parameters. file_name (text field) The filename of the xml expectations file.
Test Targets Test targets represent entities that QMTest uses to run tests. See for an overview of how QMTest uses targets.
Target Specification Each target specification includes the following: The name of the target. This is a name identifying the target, such as the host name of the computer which will run the tests. Target names should be unique in a single target file. The target class. Similar to a test class, a target class is a Python class which implements a type of target. As with test classes, a target class is identified by its name, which includes the module name and the class name. For example, thread_target.ThreadTarget is the name of a target class, provided by QMTest, which runs tests in multiple threads on the local computer. QMTest includes several target class implementations. See for details. A target group name. The test implementor may choose the syntax of target group names in a test implementation. Target groups may be used to encode information about target attributes, such as architecture and operating system, and capabilities. Optionally, a target specification may include additional properties. Properties are named and have string values. Some target classes may use property information to control their configuration. For instance, a target class which executes tests on a remote computer would extract the network address of the remote computer from a target property.
Target Classes QMTest includes these target class implementations.
<classname>SerialTarget</classname> The serial_target.SerialTarget target class runs tests one after the other on the machine running QMTest. If you use a SerialTarget, you should not also use any other targets, including another SerialTarget at the same time.
<classname>ThreadTarget</classname> The thread_target.ThreadTarget target class runs tests in one or more threads on the machine running QMTest. The ThreadTarget can be used to run multiple tests at once. ThreadTarget uses the following properties: The concurrency specifies the number of threads to use. Larger numbers of threads will allow QMTest to run more tests in parallel. You can experiment with this value to find the setting that allows QMTest to run tests most quickly.
<classname>ProcessTarget</classname> The process_target.ProcessTarget target class run tests in one more processes on the machine running QMTest. This target class is not available on Windows. Like ThreadTarget, ProcessTarget can be used to run multiple tests simultaneously. In general, you should use ThreadTarget instead of ProcessTarget to maximize QMTest performance. However, on machines that do not have threads, ProcessTarget provides an alternative way of running tests in parallel. ProcessTarget uses the following properties: The concurrency specifies the number of processes to use. Larger numbers of processes will allow QMTest to run more tests in parallel. You can experiment with this value to find the setting that allows QMTest to run tests most quickly. QMTest uses the path given by the qmtest property to create additional QMTest instances. By default, the path /usr/local/bin/qmtest is used.
<classname>RemoteShellTarget</classname> The rsh_target.RSHTarget target class runs tests on a remote computer via a remote shell invocation (rsh, ssh, or similar). This target uses a remote shell to invoke a program similar to the qmtest command on the remote computer. This remote program accepts test commands and responds with results from running these tests. To use RSHTarget, the remote computer must have QMTest installed and must contain an identical copy of the test database. QMTest does not transfer entire tests over the remote shell connection; instead, it relies on the remote test database for loading tests. In addition, the remote shell program must be configured to allow a remote login without additional intervention (such as typing a password). If you use rsh, you can use an .rhosts file to set this up. If you use ssh, you can use an SSH public key and the ssh-agent program for this. See the corresponding manual pages for details. RSHTarget uses all of the properties given above for ProcessTarget. In addition, RSHTarget uses the following properties: The remote_shell property specifies the path to the remote shell program. The default value is ssh. The remote shell program must accept the same command-line syntax as rsh. The host property specifies the remote host name. If omitted, the target name is used. The database_path property specifies the path to the test database on the remote computer. The test database must be identical to the local test database. If omitted, the local test database path is used. The arguments property specifies additional command-line arguments for the remote shell program. The value of this property is split at space characters, and the arguments are added to the command line before the name of the remote host. For example, if you are using the ssh remote shell program and wish to log in to the remote computer using a different user account, specify the -l username option using the arguments property.
Hosts A number of test classes delegate the execution of executables to a dedicated Host class, for example to allow parts of the test to be run on a different platform (such as when cross-compiling and cross-testing). To achieve that, a number of Host subclasses are provided that can be used to execute code in different ways. Typically, a test class will query the Host instance to use from a context variable.
<classname>local_host.LocalHost</classname> A LocalHost is the machine on which Python is running.
<classname>ssh_host.SSHHost</classname> An SSHHost is accessible via ssh or a similar program. The SSHHost host uses the following parameters. host_name (text field) The name of the remote host. ssh_program (text field) The path to the remote shell program. ssh_args (set field) The arguments to the remote shell program. scp_program (text field) The path to the remote copy program. scp_args (set field) The arguments to the remote copy program. default_dir (text field) The default directory on the remote system.
<classname>ssh_host.RSHHost</classname> An RSHHost is a SSHHost that uses rsh instead of ssh.
<classname>simulator.Simulator</classname> A Simulator is a semi-hosted simulation environment. The Simulator host uses the following parameters. simulator (text field) The simulation program. simulator_args (set field) Arguments to the simulation program.
Result Streams and Result Readers Result streams and result readers are the means that allow QMTest to externalize and internalize test results.
<classname>text_result_stream.TextResultStream</classname> A TextResultStream displays information textually, in human readable form. It is used when QMTest is run without a graphical user interface.
<classname>xml_result_stream.XMLResultStream</classname> An XMLResultStream writes out results as XML. The resulting file can be read back in using an XMLResultReader.
<classname>pickle_result_stream.PickleResultStream</classname> A PickleResultStream writes out results as Python pickles. The resulting file can be read back in using a PickleResultReader.
<classname>sql_result_stream.SQLResultStream</classname> An SQLResultStream writes results out to an SQL database. To read results from an SQL database use SQLResultReader.
The <application>QMTest</application> Configuration File QMTest allows you to set up a per-user configuration file that contains your personal preferences, defaults, and settings. The configuration file is named $HOME/.qmrc. On Windows, you may have to set the HOME environment variable manually. The QMTest configuration file is a plain text file, with a format similar to that used in Microsoft Windows .INI files. It is divided into sections by headings in square brackets. Three sections are supported: [common] contains configuration variables common to all the &qm; tools, while [test] contains configuration variables specific to QMTest. Within each section, configuration variables are set using the syntax variable=value. Here is a sample &qm; configuration file: > cat ~/.qmrc [common] browser=/usr/local/bin/mozilla
Configuration Variables These configuration variables are used in all &qm; tools. You should define them in the [common] section of your &qm; configuration file. browser (UNIX-like platforms only) The path to your preferred web browser. If omitted, &qm; attempts to run mozilla. The &qm; GUI does not correctly with Netscape 4 due to limitations in the support for JavaScript and DOM in that browser. command_shell The shell program to run a single shell command. The value of this property is the path to the shell executable, optionally followed by command-line options to pass to the shell, separated by spaces. The shell command to run is appended to the command. On GNU/Linux systems, the default is /bin/bash -norc -noprofile -c. On other UNIX-like systems, the default is /bin/sh -c. click_menus If this option is not present, or has the value 0, menus in the GUI are activated by moving the mouse over the menu name. If this option has the value 1, the menus are activated by clicking on the menu name. remote_shell (UNIX-like platforms only) The program used for running commands on remote computers. The program must accept the same syntax as the standard rsh command, and should be configured to run the command remotely without any additional interaction (such as requesting a password from the TTY). The default value is /usr/bin/ssh. script_shell The shell program to run a shell script. The value of this property is the path to the shell executable, optionally followed by command-line options to pass to the shell, separated by spaces. The filename of the shell command is appended to the command. On GNU/Linux systems, the default is /bin/bash -norc -noprofile. On other UNIX-like systems, the default is /bin/sh.
qmtest-2.4.1/doc/qm-opl.xml0000664000076400007640000001070311107032207015055 0ustar stefanstefan
I. REQUIREMENTS ON BOTH UNMODIFIED AND MODIFIED VERSIONS Open Publication work may be reproduced and distributed in whole or in part, in any medium physical or electronic, provided that the terms of this license are adhered to, and that this license or an incorporation of it by reference is displayed in the reproduction. Proper form for incorporation of this license by reference is as follows:
Copyright © 2000, 2001 by CodeSourcery LLC. This material may be distributed only subject to the terms and conditions set forth in the Open Publication License.
Commercial redistribution of material covered by this license is permitted. Any publication in standard (paper) book form shall require the citation of the original author and (where applicable) publisher. II. COPYRIGHT The copyright to each Open Publication is owned by its author(s) or designee(s). III. SCOPE OF LICENSE The license terms below apply to all Open Publication works. AGGREGATION. Mere aggregation of Open Publication works or a portion of an Open Publication work with other works or programs on the same media shall not cause this license to apply to those other works. The aggregate work shall contain a notice specifying the inclusion of the Open Publication material and appropriate copyright notice. SEVERABILITY. If any part of this license is found to be unenforceable in any jurisdiction, the remaining portions of the license remain in force. NO WARRANTY. Open Publication works are licensed and provided `as is' without warranty of any kind, express or implied, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose or a warranty of non-infringement. IV. REQUIREMENTS ON MODIFIED WORKS All modified versions of documents covered by this license, including translations, anthologies, compilations and partial documents, must meet the following requirements: The modified version must be labeled as such. The person making the modifications must be identified and the modifications dated. Acknowledgement of the original author and publisher if applicable must be retained according to normal academic citation practices. The location of the original unmodified document must be identified. The original author's (or authors') name(s) may not be used to assert or imply endorsement of the resulting document without the original author's (or authors') permission. V. GOOD-PRACTICE RECOMMENDATIONS In addition to the requirements of this license, it is requested from and strongly recommended of redistributors that: If you are distributing Open Publication works on hardcopy or CD-ROM, you provide email notification to the authors of your intent to redistribute at least thirty days before your manuscript or media freeze, to give the authors time to provide updated documents. This notification should describe modifications, if any, made to the document. All substantive modifications (including deletions) be either clearly marked up in the document or else described in an attachment to the document. Finally, while it is not mandatory under this license, it is considered good form to offer a free copy of any hardcopy and CD-ROM expression of an Open Publication-licensed work to its author(s).
qmtest-2.4.1/doc/qm.mod0000664000076400007640000000407311110104121014234 0ustar stefanstefan QM"> QMBuild"> QMConfig"> QMTest"> QMTrack"> API"> DTD"> DTML"> FAQ"> GUI"> HTML"> IDB"> IID"> MIME"> RDBMS"> SQL"> URL"> XML"> qmtest"> qmtrack"> FIXME"> > "> PASS"> FAIL"> ERROR"> UNTESTED"> qmtest-2.4.1/doc/cli_reference.xml0000664000076400007640000013251611110104161016435 0ustar stefanstefan %entities; ]> Invoking &qmtest; All &qmtest; functionality is available using the qmtest command.
<command>qmtest</command>
Synopsis qmtest option command command-option argument
Options These options can be used with any &qmtest; command, and must precede the command name on the command line. All options are available in a "long form" prefixed with "&dashdash;" (two hyphens). Some options also may be specified in a "short form" consisting of a single hyphen and a one-letter abbreviation. Short-form options may be combined; for example, -abc is equivalent to -a -b -c. path path Use the test database located in the directory given by path. This flag overrides the value of the environment variable QMTEST_DB_PATH. If neither this flag nor the environment variable is specified, &qmtest; assumes that the current directory should be used as the database. See . Display help information, listing commands and general options for the qmtest command. Describe the version of &qmtest; in use. Additional options are available for specific commands; these are presented with each command. Options specific to a command must follow the command on the command line. Specify the () option after the command for a description of the command and a list of of available options for that command.
<command>qmtest create</command>
Summary Create a new extension instance.
Synopsis qmtest create option kind descriptor
Description The qmtest create creates a new extension instance. For example, this command can be used to create a new test or resource. For a list of the kinds of extensions supported by &qmtest;, run qmtest extensions. The kind must be one of these extension kinds. If the option is provided then the new instance is created in the test database. The argument to the option gives the name of the instance. Otherwise, the extension is written as XML to the filename specified by option, or to the standard output if no is specified. The descriptor specifies an extension class and (optionally) attributes for that extension class. The form of the descriptor is class(attributes), where the attributes are of the form attr = "val". If there are no attributes, the parentheses may be omitted. The class may be either the path to an extensing extension or a QMTest class name in the form module.class. If the option has been provided, QMTest will look for an existing extension in the test database named class. If the option has not been provided, QMTest will look for an XML file named class. In either case, if an existing extension cannot be found, the class is interepreted as the name of an extension class. The attributes used to construct the extension instance come from three sources: the attributes in the extant extension (if the class is the path to an extension file), the options provided on the command line, and the explicit attributes provided in the descriptor. If multiple values for the the same attribute name are provided, the value used is taken from the first source in the following list for which there is a value: the rightmost attribute provided in the descriptor, the extension file, or the rightmost present on the command line. The create command accepts these options: name=value name=value Set the target class argument name to value. The set of valid argument names and valid values is dependent on the extension class in use. id id Add the extension instance to the database, using id as the name of the instance. file file Write the extension instance to file.
Example This command: creates a file called rs containing an instance of TextResultStream. This command: > qmtest create --id=simple -a program=testprog test command.ExecTest creates a test named "simple" that executes the program testprog: This command: > qmtest create --id=copy test simple creates a copy of the "simple" test, naming the new version "copy".
<command>qmtest create-target</command>
Summary Create a new target.
Synopsis qmtest create-target option name class group
Description The qmtest create-target command creates a new target. A target is an entity that runs tests; normally, a target corresponds to a particular machine. The target's name and class must be specified. An optional group may also be specified. When &qmtest; decides which target to use to run a particular tests, it will select a target that matches the test's requested target group. The create-target command accepts these options: name=value name=value Set the target class argument name to value. The set of valid argument names and valid values is dependent on the target class in use. file file Write the target description to the indicated file. If there are already targets listed in file, they will be preserved, except that any target with the same name as the new target will be removed. If this option is not present, the file used will be the QMTest/targets file in the test database directory.
<command>qmtest create-tdb</command>
Summary Create a new test database.
Synopsis qmtest create-tdb option
Description The qmtest create-tdb command creates a new, empty test database. A test database is a directory in which &qmtest; stores configuration files, tests, and other data. Certain test database classes may also store data elsewhere, such as in an external relational database. The test database is created in the directory specified by () option or by setting the QMTEST_DB_PATH environment variable. If no database path is specified, &qmtest; assumes that the current directory is the test database. By default, &qmtest; creates a new test database that uses the standard XML-based implementation. (See for information about writing a test database class.) The create-tdb command accepts these options: name=value name=value Set the database attribute name to value. The set of attribute names and valid values is dependent on the database class in use. The default database class accepts no attributes. class class Use the test database class given by class. The class may have the general form described in . Once you create a test database, you cannot change the test database implementation it uses. If you do not use this option, &qmtest; will use the default test database implementation, which uses an XML file format to store tests.
<command>qmtest gui</command>
Summary Start the graphical user interface.
Synopsis qmtest gui option
Description The qmtest gui starts the graphical user interface. The graphical user interface is accessed through a web browser. You must have a web browser that supports JavaScript to use the graphical interface. &qmtest; has been tested with recent versions of Internet Explorer and Netscape Navigator. Other web browsers may or may nor work with &qmtest;. The gui command accepts these options: address address Bind the server to the indicated internet address, which should be a dotted quad. By default, the server binds itself to the address 127.0.0.1, which is the address of the local machine. If you specify another address, the server will be accessible to users on other machines. QMTest does not perform any authentication of remote users, so you should not use this option unless you have a firewall in place that blocks all untrusted users. name=value name=value For details about this option, see the description of the qmtest run command. file file For details about this option, see the description of the qmtest run command. Run the QMTest GUI as a daemon. In this mode, QMTest will detach from the controlling terminal and run in the background until explicitly shutdown. count count For details about this option, see the description of the qmtest run command. Do not attempt to start a web browser when starting the GUI. &qmtest; will still print out the URL at which the server can be accessed. You can then connect to this URL manually using the browser of your choice. file file For details about this option, see the description of the qmtest run command. Specify the path to which the QMTest GUI will write its process ID. This option is useful if you want to run QMTest as a daemon. If this option is not provided, no PID file is written. If you specify this option, but path is the empty string, QMTest will check the .qmrc configuration file for a pid-file entry. If there is no such entry, QMTest will use an appropriate platform-specific default value. Specify the port on which the &qmtest; GUI will listen for connections. If this option is not provided, &qmtest; will select an available port automatically. file file For details about this option, see the description of the qmtest run command.
<command>qmtest extensions</command>
Summary List available extension classes.
Synopsis qmtest extensions option
Description The qmtest extensions lists available extension classes and provides a brief description of each class. You can use this command to list all of the available extension classes, or to list all of the available extension classes of a particular type. For example, you can use this command to list all of the available test classes. The extensions command accepts these options: kind kind List the available extension classes of the indicated kind. The kind must be one of test, resource, target, database, host, or run_database.
<command>qmtest describe</command>
Summary Describe an extension class.
Synopsis qmtest describe option kind name
Description The qmtest describe displays a description of the extension name. The describe command accepts these options: kind Describe an extension class of the indicated kind. The kind must be one of test, resource, target, database, host, or run_database. Provide a long (i.e. more detailed detailed) description of the extension. name name Describe the given attribute.
<command>qmtest ls</command>
Summary List the contents of the test database.
Synopsis qmtest ls option name
Description The qmtest ls lists the contents of the database, just as the UNIX ls command lists the contents of the filesystem. If this command is used with no options, QMTest will list the names of the entries in the root directory of the test database. If one or more names are supplied, then QMTest will list those items, rather than the root directory. If a name refers to a directory, then the contents of that directory will be displayed. The ls command accepts these options: Use a detailed output format that displays the kind and extension class associated with each item. Display details such as individual attributes for each item. Recursively list the contents of directories.
<command>qmtest register</command>
Summary Register an extension class.
Synopsis qmtest register kind class-name
Description The qmtest register registers an extension class with QMTest. As part of this process, QMTest will load your extension class. If the extension class cannot be loaded, QMTest will tell you what went wrong. QMTest will search for your extension class in the directories it would search when running tests, including those given by the environment variable QMTEST_CLASS_PATH. The kind argument tells QMTest what kind of extension class you are registering. If you invoke qmtest register with no arguments it will provide you with a list of the available extension kinds. The class-name argument gives the name of the class in the form module.Class. QMTest will look for a file whose basename is the module name and whose extension is either py, pyc, or pyo.
<command>qmtest run</command>
Summary Run tests or test suites.
Synopsis qmtest run option test-name suite-name
Description The qmtest run command runs tests and displays the results. If no test or suite names are specified, &qmtest; runs all of the tests in the test database. If test or suite names are specified, only those tests or suites are run. Tests listed more than once (directly or by inclusion in a test suite) are run only once. The run command accepts these options: name=value name=value Annotate the test run by inserting the named annotation name with the value value into all result streams. This option may be specified multiple times. name=value name=value Add a property to the test execution context. The name of the property is name, and its value is set to the string value. This option may be specified multiple times. file file Read properties for the test execution context from the file file. The file should be a text file with one context property on each line, in the format name=value. Leading and trailing whitespace on each line are ignored. Also, blank lines and lines that begin with "#" (a hash mark) are ignored as comments. This option may be specified more than once, and used in conjunction with the option. All of the context properties specified are added to the eventual context. If a property is set more than once, the last value provided is the one used. If this option is not specified, but a file named context exists in the current directory, that file is read. The properties specified in this file are processed first; the values in this file can be overridden by subsequent uses of the option on the command line. format format Control the format used when displaying results. The format specified must be one of full, brief, stats, batch, or none. The brief format is the default if &qmtest; was invoked interactively; the batch format is the default otherwise. In the full format, &qmtest; displays any annotations provided in test results. In the brief mode only the causes of failures are shown; detailed annotations are not shown. In the stats format, no details about failing tests are displayed; only statistics showing the number of passing and failing tests are displayed. In the batch mode, the summary is displayed first, followed by detailed results for tests with unexpected outcomes. In the none mode, no results are displayed, but a results file is still created, unless the option is also provided. count count Run tests in multiple count concurrent processes on the local computer. On multiprocessor machines, the processes may be scheduled to run in parallel on different processors. &qmtest; automatically collects results from the processes and presents combines test results and summary. By default, one process is used. This option may not be combined with the () option. Do not produce a test results file. file file Write full test results to file, in QMTest's machine-readable file format. Use a "-" (a hyphen) to write results to the standard output. If neither this option nor is specified, the results are written to the file named results.qmr in the current directory. file file Treat file as a set of expected outcomes. The file is usually a results file created either by using the qmtest run or by saving results in the graphical user interface. If file does not appear to be such a file, it is interpreted as an extension descriptor, as described in . QMTest will expect the results of the current test run to match those specified in the file and will highlight differences from those results. Run the tests in a random order. This option can be used to find hidden dependencies between tests in the testsuite. (You may not notice the dependencies if you always run the tests in the same order.) file Rerun only those tests that had unexpected outcomes. The tests run are determined as follows. QMTest starts with all of the tests specified on the command line, or, if no tests are explicitly specified, all of the tests in the database. If no expectations file is specified (see the description of the option), then all tests that passed in the results file indicated by the option are removed form the set of eligible tests. If an expectations file is specified, then the tests removed are tests whose outcome in the results file indicated by the option is the same as in the expectations file. The provides a simple way of rerunning failing tests. If you run your tests and notice failures, you might try to fix those failing tests. Then, you can rerun the failing tests to see if you succeeded by using the option. Specify an additional output result stream. The descriptor is in the format described in . integer If the is used, &qmtest; randomizes the order in which tests are run, subject to the constraints described in . By default, the random number generator is seeded using the system time. For debugging purposes, it is sometimes necessary to obtain a reproducible sequence of tests. Use the option to specify the seed for the random number generator. Note that even with the same random number seed, if tests are run in parallel, scheduling uncertainty may still produce variation in the order in which tests are run. file file Use targets specified in target specification file file. If this option is not present, the QMTest/targets in the test database directory will be used. If that file is not present, the tests will be run in serial on the local machine.
<command>qmtest summarize</command>
Summary The qmtest summarize displays information stored in a results file.
Synopsis qmtest summarize option results-file test-name suite-name
Description The qmtest summarize extracts information stored in the results-file (or results.qmr, if no results-file is specified) and displays this information on the console. The information is formatted just as if the tests had been run with qmtest run, but, instead of actually running the tests, QMTest reads the results from the results-file. If the results-file is not a valid results file, it is interpreted as an extension descriptor, as described in . You can use the descriptor syntax to read results stored in formats that are not "built-in" to QMTest. The summarize command accepts the following options: format format For details about this option, see the description of the qmtest run command. file file Write full test results to file, in QMTest's machine-readable file format. Use a "-" (a hyphen) to write results to the standard output. file file For details about this option, see the description of the qmtest run command. Specify an additional output result stream. The descriptor is in the format described in .
<command>qmtest report</command>
Summary The qmtest report generates an xml report from a set of test result files.
Synopsis qmtest report -o output -f report-file -e expectation-file
Description The qmtest report extracts information stored in one or more result files and generates an xml report file from it. This report file is then typically processed using xslt to generate html or pdf versions of the report. The report command accepts the following options: Generate a flat listing of test results, instead of reproducing the database directory tree in the report. output file output-file The name of the file to write the report into.
Environment Variables &qmtest; recognizes the following environment variables: QMTEST_CLASS_PATH If this environment variable is set, it should contain a list of directories in the same format as used for the system's PATH environment variable. These directories are searched (before the directories that &qmtest; searches by default) when looking for extension classes such as test classes and database classes. QMTEST_DB_PATH If this environment variable is set, its value is used as the location of the test database, unless the () option is used. If this environment variable is not set and the option is not used, the current directory is used as the test database.
Configuration Variables These configuration variables are used by QMTest. You should define them in the [qmtest] section of your &qm; configuration file. pid-file The default path to use when creating a PID file with the option. (See for more information about this option.) If this entry is not present, an appropriate platform-specific default value is used.
Return Value If QMTest successfully performed the action requested, &qmtest; returns 0. For the qmtest run or qmtest summarize commands, success implies not only that the tests ran, but also that all of the tests passed (if the option was not used) or had their expected outcomes (if the option was used). If either the run command or the summarize command was used, and at least one test failed (if the option was not used) or had an unexpected outcome (if the option was used), qmtest returns 1. If QMTest could not perform the action requested, qmtest returns 2.
qmtest-2.4.1/doc/design/0000775000076400007640000000000011122067201014375 5ustar stefanstefanqmtest-2.4.1/doc/design/qmtest/0000775000076400007640000000000011122067201015712 5ustar stefanstefanqmtest-2.4.1/doc/design/qmtest/impl.xml0000664000076400007640000003517111110104205017375 0ustar stefanstefan Implementation This chapter describes the Python classes that correspond to the major &qmtest; concepts. Most of these classes are designed as polymorphic classes that can be replaced by users to create customized testing environments. Therefore, the information provided here does not go beyond the interfaces of these classes; a valid implementation of each class must provide at least the functionality described in these interfaces.
Class <classname>Test</classname> Each test class must derive from the Test class, which has the following interface:
Class <classname>Suite</classname> The Suite class has the following interface:
Class <classname>Action</classname> Each action class must derive from the Action class:
Class <classname>Database</classname> The Database class has the following interface:
Class <classname>Engine</classname> The Engine class has the following interface:
Class <classname>Context</classname> An instance of the Context class is passed to each test when it is run. By examining the context object, the test can obtain configuration parameters provided by the tester, such as the current machine architecture, or optional arguments to provide to the tested program, or the paths to programs that must be invoked. The Context class has the following interface:
Test Database: Default Implementation The test database is responsible for mapping test IDs to test instances. The way in which a test database does this will differ on the database in use, and much of the power of &qmtest; comes from the ability to provide specialized test databases. This section describes the default test database implementation provided with &qmtest;. The next section provides an example of a specialized test database that could be used to deal with test specifications in a form other than provided here.
Data Storage The physical database will consist of a directory in the filesystem, together with its subdirectories and the files contained in all of these directories. Each file within this directory hierarchy that ends with the extension .qmt contains exactly one test specification. The file whose path is given by foo/bar/baz.qmt relative to the root of the database will have the test ID "foo.bar.baz". (By using a particular extension for test files, desktop environments can associate particular icons with test files. Using a particular extension, together with the requirement that there be only one test per file, means that both locating a particular test in the database and enumerating all the tests in the database are speedy operations.)
Test Specifications The test specifications themselves will be represented as &xml;, using the &dtd; presented in .
&dtd; for test specitication ]]>
The formal public identifier for this &dtd; is "-//Software Carpentry//DTD QMTest V0.1//EN" For example, suppose that Diana Dowhile's compiler crashes when given the following input: int main () { volatile int x = 2; return x - 2; } Diana determines that the test case causes the compiler to crash only when the -fpic flag is provided to the compiler. Diana might use the test specification presented in . &xml; representation of test Compile ]]> '-fpic' C PIC ]]> This specification indicates that the test class to be used is the Compile class. This class takes two arguments: the text of a program to compile, and the flags to use when compiling the test program. When the instance is executed, the program test will be written to a temporary file, and the compiler will be run. The test specification also indicates that the test is in two particular categories. The "C" categorization indicates that this test exercises the C programming language components of teh compiler; if Diana wishes to test only C, as opposed to C++ or Fortran programs, she could indicate that by asking &qmtest; to run only those tests in the "C" category. The "PIC" categorization indicates that the test tests the -fpic option; after a change to the code that deals with this option, she could choose to rerun only those tests in the "PIC" category.
Test Classes Each test specification indicates the test class to which it belongs. In order to instantiate that test class, the database must locate the Python code for that test class. The test database will search for a corresponding .py or .pyc file in the following directories in order to find the test class: The directories provided in the QMTEST_CLASSPATH environment variable. This environment variable will use the same syntax as the PATH environment variable on the system on which &qmtest; is running. The directory containing the test specification, and its parents in the directory hierarchy, stopping at the directory that forms the root of the test database. Those directories containing standard test classes provided by &qmtest;. Note that the directories in the PYTHONPATH environment variable is not searched, so as to avoid accidentally interpreting ordinary Python classes as test classes.
Suites As mentioned above, each subdirectory of the test database is implicitly considered a test suite. Thus, if there is a directory in Diana's database named parser, she can run all the test in this subdirectory (and the subdirectories within it) by asking &qmtest; to run the parser suite. However, test suites do not always naturally form a tree. (See the .) Users may specify suites in addition to those provided implicitly by the database. These suites a represented by files with the .qms extension. Each such file contains the names of tests, given relative to the directory containing the .qms file. The ID for a test suite is computed in precisely the same way as the ID for a test. A test and a test suite may have the same ID.
Test Database: Custom Implementation In this section, we show how &qmtest; meets the requirement that users be able to execute tests specified in formats other than &qmtest;'s default &xml; format. In particular, by creating a specialized test database, Diana can reuse an extant test suite, which consists of C source code with special comments that indicate the compiler command-line flags to use when executing particular tests. Most of the behavior specified by the default test database implementation will work as-is, but Diana needs to modify the function that maps test IDs to test instances. Rather than search for a .qmt, Diana needs to search for a .c file. Instead of finding &xml; in the file describing the test, she must extract the arguments to the Compile test class from the special comments in the file. Diana will create her specialized test database class by inheriting from the standard class and overriding a method or two. Then, by using this alternative test database class, Diana can use &qmtest;'s execution and reporting capabilities to execute her extant tests.
qmtest-2.4.1/doc/design/qmtest/req.xml0000664000076400007640000006556511110104225017237 0ustar stefanstefan Requirements This section lists requirements derived from the use cases presented above, and from the discussions on the Software Carpentry mailing list. The four most important requirements (accuracy, usability, reproducibility, and conservatism) are presented first; secondary or derived requirements follow.
Accuracy The most important requirement for &qmtest; is accuracy: it must never report that a test has succeeded when in fact it has failed, or vice versa. (In statistical terminology, there must be no false positives and no false negatives.) A corollary of this requirement is that &qmtest; must always execute at least all of the tests requested by the user. Ideally, it should only execute exactly these tests, but in practice, it is acceptable for &qmtest; to run more tests than the user asked for, so long as all of the tests that were asked for are run.
Small-Scale Usability Small-scale testing must be easier to do with &qmtest; than by hand. If &qmtest; requires users to do things that only pay off on medium or large projects, many of those users will choose to do ad hoc testing initially, instead of using &qmtest;. In theory, users could then switch to &qmtest; when its adoption cost was outweighed by its benefits, but in practice, those ad hoc test suites will usually grow (or, more likely, rust) as their projects grow.
Reproducibility Test execution must be reproducible: &qmtest; must be able to recreate the starting point for a particular run of a test exactly. This requirement is necessary in order to minimize the burden on human users: without it, it could be necessary to repeatedly re-run a test that reported an error or failure in order to isolate the fault. Note that this does not mean that the test result is exactly reproducible—some tests of network software and user interfaces are intrinsically non-deterministic—but all controllable variables (such as random number generator seeds) must be stored in a re-executable way.
Conservatism &qmtest; must use existing standards, syntax, conventions, and tools wherever possible. In this way, it will be easier for users to adopt &qmtest;, easier for developers to build and modify &qmtest;, and easier for other tools to integrate with &qmtest;, and easier to take advantages of improvements to other components used in &qmtest;. The specific implications of this requirement are: Where &qmtest; needs structured data storage, the format of that storage will be defined in terms of &xml;. This does not mean that only &xml; will be used: flat text, executable scripts, relational database schemas, persisted Python scripts, and other formats may be supported as well. However, since &xml; is more constraining than these formats, designing in terms of it will ensure that all features are available in all modes. Where &qmtest; needs to expose quoting rules, floating-point numbers, or other programmatic constructs to users, it will use the syntax defined for Python. Note that this does not mean that &qmtest; will be Python-centric; the rationale is simply that there is no point defining yet another set of rules for writing things like: output < 5.0 and command != "start\n" Where &qmtest; needs data formats (e.g. parameters for procedure calls), it will use the rules included in the draft SOAP standard. Again, this does not mean that only SOAP will be used in the system; as with programmatic syntax, however, there seems to be little point developing yet another set of rules for describing or constraining such things as arrays of strings. A "negative" standards requirement is that &qmtest; must not require all tests to be command-line applications. In particular, tests may have access to standard input and standard output, and may be able to report success or failure by exiting with a zero or non-zero status, but &qmtest; does not insist upon this. This requirement is necessary because many applications of interest may be long-lived services (e.g. a web server), or may rely on a framework (such as the Microsoft Foundation Classes or some Java gui frameworks) that does not provide standard input or standard output.
Dependent and Independent Tests &qmtest; must allow programmers to specify dependencies among tests, and must prevent dependent tests from being executed if an error occurred in an antecedent. For obvious reasons, dependencies among tests must be acyclic; &qmtest; must detect and report cyclic dependencies. &qmtest; should try to detect and report cyclic dependencies before executing any tests, but is not required to do this, since this may not be possible if tests are being generated on the fly. Finally, it must be possible to separate setup and cleanup from particular tests, so that the modified environments required for dependent tests are not destroyed before those tests are executed. &qmtest; must trace dependencies among tests, and automatically determine when to set up and clean up. If possible, &qmtest; should share dependency detection and management functionality with &qmbuild;. One scenario in which significant setup or cleanup actions are required is database testing. The test system should be able to populate an empty database with several million records, perform tests that query the database, and then remove the database from the user's system. It would be woefully inefficient to re-populate the database for each test, so the setup and cleanup actions must be able to span multiple tests.
Expected and Unexpected Results There are often periods in a development cycle during which certain tests are expected to fail. For example, if Extreme Programming's "test, then code" development model is being used, all of a module's tests will initially fail. &qmtest; must therefore allow programmers to specify that some tests are expected to fail. It must also report expected failures separately from passes, unexpected failures, and other results. In many cases, tests will fail under some configurations and not others. For example, a compiler might generate correct code for a PowerPC but incorrect code for a SPARC. Similarly, a scientific application might perform correctly when using a conventional matrix representation, but incorrectly when using an optimized representation. Therefore users must be able to indicate that certain tests are expected to fail only in certain circumstances.
Reporting &qmtest; must be able to report test results in textual, human-readable form. This is necessary for two reasons: While all version control systems are able to find and display micro-differences between text files, most are not able to do this for binary files. Since users may archive test results along with the tests themselves (and the code being tested), &qmtest; must be designed to facilitate this. Many developers still use command-line tools, and will want to run &qmtest; from the command line. Its output must therefore be viewable without external helper applications, such as web browsers. This requirement does not imply that flat text will be &qmtest;'s only, or usual, output format. In particular, &xml;-aware tools are maturing and becoming common. &qmtest; must therefore be able to report and store test results as &xml;. This will make it easier for &xml;-aware integrated development environments (IDEs) and version control systems to leverage the semantic content of &qmtest;'s output. Requiring test authors to write tests that can generate output in two or more formats is an unacceptable burden. &qmtest; must therefore provide test result formatting and reporting functions in all programming languages of interest. The format in which these functions report results must be controlled by a single switch, i.e. there cannot be separate functions for different reporting formats.
Regeneration of Reference Results Users are often interested in checking whether or not a particular change to a program causes new failures. Therefore, &qmtest; must be able to determine automatically the expected outcome of a test by comparing it to a known set of outcomes. In this way, users can discern the difference between the situation in which a test is failing independently of a source-code change, and the situation in which a test is failing due to a source code change. For example, &qmtest; might be run nightly to generate reference results. Then, even if an erroneous change was checked in the previous day, developers would realize that their current changes were not responsible. Of course, &qmtest; would also generate a report indicating that the reference results had regressed from one night to the next.
Test Suites &qmtest; must allow test authors to aggregate tests into test suites so that large collections of tests can be run at once. It is natural to allow test suites to contain other test suites. For example, this facilitates building a test suite for an entire program out of the test suites for each component of the program. Although test suites may contain other test suites, test suites do not in general form a tree. For example, an organization might wish to execute a few representative tests from the component test suites each time a change was made to any part of the product. Thus, a single test can be in more than one test suite. Because test suites are collections of tests, there is no sense in which a suite "passes" or "fails". There is no unique way in which to classify an arbitrary combination of pass, fail, and error outcomes into a single result. However, as discussed below users can use summary reports to obtain information about the number of tests which passed or failed within a particular suite.
Test Identification &qmtest; must support the use of human-readable and memorable test names so that users can easily recognize failing tests and communicate with each other about the tests. Test names should be hierarchical to facilitate easy organization and easy storage of tests in the file system. These identifiers must be persistent; the name of a test must not change as tests are added or removed from the test database.
Summary Reporting &qmtest; must summarize the outcomes (passes or failures) of the tests executed by producing a count of the number of tests for which each outcome occurred. This reporting must be hierarchical: users must be able to inspect the summaries for suites, the test suites within those suites, and so on. Finally, reporting and recording must be independent, i.e. &qmtest; must be able to record more information about test results than it provides in summary reports, so that users can analyze failures in more detail.
Extra Information In many cases, it is useful to include more information than simply the outcome (pass or fail) of the test. For example, it may be desirable to have tests report execution time, memory usage, number of context switches, or code coverage. &qmtest; must allow tests to contain and report extra named values, while the summary reporting system must allow extra named values to be combined hierarchically. One common case in which extra information is provided is to explain why specific tests were untested. If a test cannot be executed except when certain conditions hold, then the factors that caused the test not to be executed should be included in the result.
Selective Execution &qmtest; must of course be able to automatically execute all the tests in a test suite. However, it must also be possible for users to explicitly specify the tests or suites to be executed, either positively, by indicating the tests which should be run, or negatively, by indicating the tests which should not be run. Summary reports for runs using selective execution should explicitly note those tests that were explicitly included or omitted. &qmtest; must be able to re-execute automatically only those tests that produced specific outcomes during a previous run. In this way, users can attempt to fix new failures, and automatically retest just the new failures. &qmtest; must be able to execute selectively only those tests that meet certain selection criteria, such as those tests that should be executed on a particular hardware platform, or those tests that test certain software components.
Test suite Organization &qmtest; must not dictate the locations of tests (or associated data) in the file system. Users require the ability to place tests in a variety of locations, partly so that they can use their usual source control systems with the tests. &qmtest; must therefore allow users to separately specify the location of tests, temporary files, and results. In order to avoid placing too great a burden on first-time users, however, &qmtest; must not require explicit specification of object locations. If the user does not explicitly specify particular locations for these various entities, the &qmtest; must provide sensible defaults. &qmtest; must not require redundant specification of test location. For example, the user should be able to specify once, at the root of the testing hierarchy, that intermediate files are to be put in /tmp, and that test results are to be archived in the same directories as tests themselves. The tests and test suites included within this hierarchy should automatically inherit this behavior.
Controlling Execution The longer a test suite takes to run, the less frequently it will be used. &qmtest; therefore must be able to execute tests concurrently when the resources needed to do so are available. In order to encourage test developers to structure tests so that they do not contain dependencies that would inhibit concurrent execution, unordered execution will be the default, although specifying test order must be supported as well. &qmtest; must also allow users to specify timeouts and resource limits when executing tests or test suites. These limits must override any that are built into the test specification.
Test Specification &qmtest; must be able to test programs using a variety of methods, including: Parsing the output from a program The test developer writes a program that contains a single call to a single test subject. When the program is executed, the test framework inspects the result of the call to the test subject (which may mean trapping errors), compares this to the result the developer expected, and produces a textual report in a standard format, from which &qmtest; can extract the test result. Note that this case includes the case in which the "call" is actually a series of calls, at the end of which a single test result is generated. Report translation from a single stand-alone executable The test developer specifies a program to be executed. This may be a special-purpose testing program, or it may be the test subject itself. The program does not produce a test result directly. Instead, the test specification describes how to translate one or more observable aspects of the program's behavior into a test result. Some common cases include: Translate a program's exit status code into a test result, automatically trapping unexpected abnormal ends such as floating point exceptions or memory access violations. Compare the program's output to a reference copy. This must be able to use an user-specified comparator to determine whether a program's output matches a reference result. Inspect one or more of the side effects of the program's execution (such as output files or changes to directory or file permissions) and produce a test report. Run the test subject and construct a report based on the output of a monitoring program, such as a memory usage checker. Multiple reports from a single executable The test developer writes a program that contains multiple calls to multiple test subjects. Each call results in a single test report, so that when the test program is run, many test reports are produced. Multiple runs of a single subject with different options All of the cases above (and below) may be repeated many times with different options, such as different command-line arguments, input files, configuration files, thresholds, and so on. &qmtest;'s users therefore must be able to specify repetition in a simple way. Direct calls to the test subject In some cases, it may be necessary or desirable to have &qmtest; itself call the test subject. In particular, the test subject may be a COM or CORBA component, a JavaBean, or a function or procedure in a dynamic language such as Perl, Python, or Ruby. In these cases, the test developer must be able to test the code without starting a separate process. As well as reading test specifications from standard &qmtest; specification files, &qmtest; must be able to extract test specifications from arbitrary legacy test descriptions, using special filters. For example, if Diana Dowhile already has 1200 test specifications embedded as specially-formatted comments in program source files; &qmtest; must allow her to recycle those files.
Programmatically Generated Tests Users will often want to generate multiple tests programmatically in cases where generating tests manually is impractical. For example, Ovide may write a small program that generates all 169 different possible cases of two rectangles overlapping (or failing to overlap). &qmtest;'s Python-based design specifically accommodates this requirement by providing interfaces by which users can produce custom test suites that generate tests on the fly.
Setup and Cleanup Individual tests and test suites may require arbitrary setup before, and cleanup after, their execution. In order to simplify test management, &qmtest; requires that setup and cleanup must be specified in the test specification, that setup and cleanup operations must be logged when tests are executed, and that tests are only executed if their setup operations complete successfully. Users are encouraged to specify cleanup operations so that they will execute correctly (i.e. return the environment to its pre-test state) even if setup and the test itself failed partially or completely. In order to avoid drowning users in detail, &qmtest; must log setup failure as a reason not to execute a test, but should only report significant setup errors by default. For example, if test B depends on test A, and test A's setup fails, &qmtest; should not report that test B has failed, since the root cause is the failure in test A's setup.
Sandboxing and Throttling A sandbox is an environment for program execution in which some or all of the facilities the program relies on have been replaced with safer, or simpler, versions. For example, a developer could construct a sandbox for a mailing list manager by replacing the SMTP library with one which wrote messages to a log file, and read messages from a specially-formatted input file, rather than interacting with the outside world. A throttle is anything used to restrict a program's execution environment, e.g. a very small heap, or a small upper bound on the number of threads a process is allowed to spawn. Throttles are typically used to simulate the effects of heavy system loads: running a program with a small heap, for example, is a good way to test how it will behave when it needs to allocate many large data structures. While future versions of &qmtest; may come packaged with sandbox and throttle libraries for specific languages and applications, these are out of the scope of the current effort. However, in order to make it easy for developers to use these facilities today (if they have them), &qmtest; must be able to record the build options of all tests, including compiler options, linked libraries, and so on.
qmtest-2.4.1/doc/design/qmtest/Makefile.in0000664000076400007640000000072411107032206017762 0ustar stefanstefan######################################################### -*-Makefile-*- # # File: Makefile # Author: Alex Samuel # Date: 2000-11-10 # # Contents: # Makefile for qmtest design document # # Copyright (C) 2000 CodeSourcery LLC # # For license terms see the file COPYING. # ######################################################################## TOPDIR = @top_srcdir@ DOCBOOK = $(wildcard *.xml) DOCBOOKMAIN = qmtest.xml include $(TOPDIR)/standard.mk qmtest-2.4.1/doc/design/qmtest/iface.xml0000664000076400007640000001461711110104235017510 0ustar stefanstefan User Interface &qmtest; will provide both a command-line and a graphical interface. The graphical user interface will provide a much more sophisticated interface than that given by the command-line interface described here. The graphical user interface design will be completed after more experience has been gained with &qmtest;.
Command-Line Interface The qmtest command invokes the &qmtest; execution engine. qmtest [ options ] subcommand [ arguments ] <command>qmtest</command> subcommands command description test suite ... Run the specified test suites. compare file1 file2 Compare two sets of test results. help Display a summary of qmtest subcommands.
<command>qmtest</command> options long option short option description database Test database to use. If not specified, use database specified in QMTEST_DATABASE environment variable (if it exists). Report result of each test on a separate line. By default, &qmtest; produces a one-line summary of results for all tests. test_filter Filter expression(s) to apply to tests. Only tests that meet the filter criteria are executed. If multiple test filters are provided, tests must satisfy all (implicit and). If no filters are provided, all tests are run. Note that allowing users to specify test IDs directly is redundant (since these are equivalent to "-t 'id==name'"). Direct test ID specification is provided for convenience. hostfile Path to file containing names of remote hosts on which to run tests. Display usage information. report_filter Filter expression(s) to apply to output. Only test results that meet the filter criteria are included in the report. If multiple filters are provided, test results must satisfy all (implicit "and"). report_style Desired output format. Options include "text" and "html". test_id Test IDs of the tests of interest. This option is strictly redundant (since tests can be selected using filters), but the "-t" option is provided as a convenience. This option may be specified more than once. Verbose output. This option may be specified more than once. file File in which to place &xml; representation of results. If this option is not specified, then &qmtest; will use a filename based on the current time. file File containing expected outcomes. The values provided in this file override those contained in the test specification itself.
Names of test suites from which to execute tests are specified as arguments. If no suite is specified, all tests in the database (that meet the filter specifications given by and options.
qmtest-2.4.1/doc/design/qmtest/core.xml0000664000076400007640000003054111110104244017363 0ustar stefanstefan Concepts This section described the core concepts and architecture of &qmtest;. Although this material is intended primarily for implementors, these concepts described here are for the most part exposed to users. The entities that are described in this chapter are precisely the entities that users will manipulate on a regular basis.
Terminology
Roles An author is someone who writes tests. A tester is someone who runs tests. Most authors are also testers, but many testers will run tests they did not write themselves (particularly when using third-party or open source software).
Test Specifications An individual test is an entity that, when run, produces a single outcome indicating success or failure. A test consists of: A test ID that uniquely identifies the test in the test database. A reference to a single test class, which defines how the test is executed. A list of arguments that are used to construct particular tests. A set of one or more properties, which provide extra information about the test. Prerequisite tests, whose outcomes must be known before this test can be executed. Optional setup and cleanup steps.
Test Identifiers A test ID is a string that identifies a test. Every test must have a unique ID within the database that contains it. A test's ID is constructed by concatenating its name with the ID of the suite that contains it, using "." as a concatenator. Suite IDs are constructed similarly. Each field in the name is composed of digits, lower-case letters, and underscores. Thus, test IDs are strings like stream.output.unable_to_open_file_for_writing. These restrictions allow safe, easy mapping of test IDs into the file system. Test IDs and suite IDs are in separate namespaces; every test database implementation must allow users to create a test and a test suite with the same ID.
Test Classes A test class defines how a particular type of test is created and run. Each test class corresponds to a Python class with the same name that contains code to execute the test and to interpret the result of that execution.
Arguments A test is instantiated by providing the arguments to the constructor for the test class. The resulting object is a test. Each test argument is a single Python expression, represented as a string, and evaluated at the time of the test object's instantiation.
Properties Properties are name/value pairs used to provide extra information about tests, such as their "weight", the operating system(s) on which it makes sense to run the test, and so on.
Prerequisites If a test A is a prerequisite of a test B, then B is only run if A produces a particular result. Normally, if A is a prerequisite of B, then B will only be run if A succeeds. &qmtest; also allows users to specify that B is to be run unless there was an error in A.
Setup and Cleanup Actions If an individual test requires setup or cleanup, then the test class itself will handle the necessary actions. However, on occasion, setup or cleanup actions will be required for a large group of tests. A test can therefore specify any number of actions, by providing a list of action IDs. Each action ID identifies an instance of an action class. Each action class provides a method that performs necessary setups, and another method that performs necessary cleanups. The setups are executed at some point before the test is run; the cleanups are executed afterwards. If any of the setups indicate failure, the test is not run; it's outcome will be UNTESTED.
Test Execution The result of executing a single test is an outcome and additional results.
Outcomes The outcome of a test indicates whether it passed, failed, or whether some exceptional situation occurred. In particular, there are four test outcomes: PASS: the test succeeded. FAIL: the test failed. ERROR: a problem occurred in the test execution environment, rather than in the tested system. For example, this outcome is used when the test class attempted to spawn a process containing an executable in order to test it, but could not because the system call to create a new process failed. UNTESTED: &qmtest; did not attempt to execute the test. For example, this outcome is used when &qmtest; determines that one of the prerequisites failed.
Results A result contains information about the execution of a single test. Each test result contains the test's ID, a test outcome, the time at which the test was executed, and zero or more properties. These may include such things as the reason why a particular test was untested, or the values of environment variables when the test was run.
Test Aggregation
Test Suite A test suite is a collection of tests and other test suites. Test suites are used to aggregate reporting of results, as in "17 out of 22 graph traversal tests reported errors". Test suites are also used to specify which tests to re-run, as in "execute all I/O tests".
Test Database A test database stores test and test suite specifications. The test database is responsible for obtaining the test instance associated with a particular test ID, or for obtaining the test instances that make up a particular suite. Although much of the subsequent discussion refers to a particular implementation of the test database (which places test specifications in the file system), &qmtest; allows for the substitution of alternative test database implementations. Such implementations might generate test specifications dynamically, or extract them from source code.
&qmtest; Components The execution engine is responsible for executing tests, as well as for collecting and recording the results. The user interface is responsible for taking commands from the user regarding which tests to run and presenting this information to the engine. The user interface is also responsible for presenting reports to the user containing summaries of the results.
Supplied Test Classes Although users may of course implement customized test classes, &qmtest; provides several test classes that users can use directly, without writing any Python code. The first of these is the ExitCode class. This class accepts as arguments the name of a program and arguments to provide the program. The test passes if the program exits with code zero, and fails if a non-zero exit code is returned. The exit code, as well as any output produced by the program on the standard output or standard error streams, is recorded in the result for the indicated test. This basic test class can be used to test a wide variety of command-line programs. &qmtest; also provides a Difference test class. This test class accepts as arguments the name of a program, arguments to provide the program, and the expected output of the program. The test passes if the tested program produces the expected output when executed. A variety of options are provided to allow for cases in which some parts of the output are expected to vary. For example, the expected output can be provided as a regular expression. The set of supplied test classes will grow as additional common testing paradigms are identified.
Expected Outcomes One of the &qmtest; requirements section is that users must be able to indicate that a particular test is presently expected to fail. Under most circumstances, that information is best kept with the test specification itself. On the other hand, users may sometimes want to use an alternative set of expected outcomes. In particular, allowing the use of an alternative set of expected outcomes allows users to use reference results. Therefore, &qmtest; allows the specification of expected outcomes both in the test specification itself, and in an external file. Because the comparison of a particular outcome is performed in the user interface, the details of the formats used has not yet been finalized.
Results Management &qmtest; stores the results of test suite runs in &xml; data files. These files are not part of the test database and are not automatically managed in any way by &qmtest;. Users are free to use whatever archiving or version control software they choose to store these files over time. Because the manipulation of these files is part of the user interface, the details of the format used has not yet been finalized.
qmtest-2.4.1/doc/design/qmtest/qmtest.xml0000664000076400007640000002673011110104252017754 0ustar stefanstefan %qm; ]> &qmtest; Design Mark Mitchell Alex Samuel Greg Wilson 2000 CodeSourcery LLC &qmlicense; version 0.2 0.2  2000 December 7 Initial revision. Introduction Many programmers do not test their code sufficiently because: Existing tools are expensive and hard to use. Thus, testing is time-consuming and tedious. Therefore, neither programmers nor their management see testing as a cost-effective approach to software quality. In addition, existing testing tools do little to inform testers about how comprehensively their program has been tested, making it difficult for testers to determine where to focus their efforts. &qmtest; is open source software, available at no charge, and is easy to use. In particular: &qmtest; has a gentle learning curve, especially for developers without software engineering training. &qmtest; is easy to install and configure, and provides simple, powerful interfaces for creating tests, running tests, and obtaining reports. &qmtest; is flexible. &qmtest can handle almost any kind of testing situation, from unit testing to full-scale integration testing. The programs tested can be large or small, written in low-level or high-level languages. &qmtest; provides feedback regarding the quality and thoroughness of testing. &qmtest; is a high-performance testing tool. &qmtest can automatically parallelize the execution of tests to take advantage of parallel machines. This document begins by describing three typical users, whose testing needs &qmtest; is designed to address. It then explores their requirements in more detail, in order to determine the features that &qmtest; must have. This analysis is followed by a discussion of the concepts that users will encounter when using &qmtest;. Finally, this document provides a design for &qmtest;'s implementation.
Acknowledgements This document has its origins in the submissions to the testing category of the Software Carpentry design competition in the spring of 2000, and in the hundreds of messages on the Software Carpentry discussion list in August--October of the same year. We are grateful to Paul Dubois (Lawrence Livermore National Laboratory), Stephen Lee (Los Alamos National Laboratory), Brian Marick (of testing.com), Ken Martin (Kitware), and Dave Thomas (a very pragmatic programmer) for their input.
User Profiles As a way of delimiting the scope of this project, this section describes three typical users whose needs &qmtest; seeks to address. These user profiles motivate the discussion in the next chapter of system requirements.
Bhargan Basepair Bhargan Basepair develops fuzzy DNA pattern-matching algorithms for a bio-technology firm called Genes'R'Us. As a semi-official service for his colleagues, he runs an overnight DNA sequence query service. Researchers e-mail DNA sequences to him; Bhargan saves these messages in files called search/a, search/b, and so on, then edits them to add query directives. Before going home at night, he runs a Unix shell script which searches the database for each sequence in the search directory. The results are put in files called search/a.out, search/b.out, and so on. Each search typically takes 15-20 minutes; he is sometimes not able to run all of the searches he has received in a single night. When Bhargan comes in the next morning, he mails out the .out files, then examines the search logs to see if he can improve the performance of his search engine. Bhargan has written a small Python program to automate this process, and now wants to test it. His main concerns are: One person's results must never be sent to someone else -- there could be legal fallout if this ever happened. Queries should never be lost or garbled: anyone who sends a valid query should eventually get a reply. The system should only run the search if the user has specified sensible parameters (so that researchers don't get results for a search other than the one they thought they were running). The test program shouldn't send mail to real people, or be sent mail from them. The corporate IT department might be willing to set up dummy user accounts for Bhargan to use in testing, but he'll probably see the millennium roll over again before it actually gets done.
Diana Dowhile Diana studied parsing algorithms for her Master's degree in Computer Science at Euphoric State University. She is now extending the C++ parser for the GNU Compiler Collection (GCC). The parser currently contains 47,000 executable lines of C and C++ in 350 functions, distributed among 18 files, and is expected to triple in size by the time the project is done. Diana starts work on each language feature by writing a few new test cases that exercise it. (Many of these tests are actually not legal C++, since one of her goals is to improve the compiler's error messages.) Diana only starts implementing the feature itself once all of her test cases are written and failing—past experience has taught her that if she writes her tests after implementing the feature, she will test against her implementation, and not against the language standard. Diana has inherited a collection of approximately 1200 tests, most written to test GCC's existing parser. These test files are scattered throughout the GCC source tree. Each test consists of one or more specially-formatted comments embedded in a C or C++ source file. A simple shell script extracts these comments, runs the C++ parser with the parameters contained in the comment, and compares the output with the expected output (which is also embedded in the comment). The test is considered a pass if the compiler emits exactly the output expected. Diana would like a tool to re-run her tests automatically, and to collect statistics on how many tests have been executed, with what results. She would also like some help generating tests: many are simple variations on a theme, such as using eighteen different kinds of constants as array subscripts, and she has made several errors in the tests themselves when copying and modifying old test files. Finally, she would like a single command to run the entire test suite simultaneously on each of the dozen or so different machines in the testing network. These machines are a mix of various versions of Unix and Microsoft Windows.
Ovide Overlay Ovide Overlay is developing new map overlay algorithms for a geographical information system. The system takes two maps A and B as input. Each map covers the same geographical area, and is divided into non-overlapping polygons. The module's output is the the map that would be generated by drawing the input maps on transparent film, and placing them on top of each other. For example, if A shows soil types, and B shows vegetation, the map shows where different kinds of plants are growing on different types of soil. In order to simplify his studies, Ovide is using maps divided into rectangles, whose vertices all lie on a [0...X]×[0...Y] grid. His reference program implements a naive "all-against-all" overlay algorithm, in which every rectangle in map A is tested against every rectangle in map B. Ovide wants to implement and test several refinements of this algorithm. His most important testing requirement is to make sure that the new algorithms generate the same results as the old ones, i.e. that his performance optimizations do not introduce bugs. His second requirement is that his test suite record and report the performance of the new algorithms on some of the test data sets—he wants to avoid the redundant work involved in building one re-execution environment for testing, and another for performance measurement.
&req.xml; &core.xml; &impl.xml; &iface.xml; &refs.xml;
qmtest-2.4.1/doc/design/qmtest/refs.xml0000664000076400007640000000650211110104257017376 0ustar stefanstefan References Brian Marick (a judge in both rounds of the ≻ design competition) is the author of a thorough survey of the art called The Craft of Software Testing. Many of his other writings are available on-line at www.testing.com Testing Computer Software, by Cem Kaner, Hung Quoc Nguyen, and Jack Falk, is a good look at testing in the real world. The Pragmatic Programmer, by Andy Hunt and Dave Thomas (both judges in the Software Carpentry design competition), includes a lot of good material on when and how to test during development. The book's web site is at www.pragmaticprogrammer.com. The Visualization Toolkit project places a lot of emphasis on testing, and has a well-developed framework for doing it systematically. This is described in the paper by William Lorensen and James Miller, Visualization Toolkit Extreme Testing: A Production Release Every Day. Some existing testing tools used in open source development include: Expect project home page DejaGnu project home page TET project home page The comp.software.testing group has a &faq;. Highlights from the ≻ discussion list are summarized on the Software Carpentry web site. The entire discussion list is archived in the mailing list archives. James Bach discusses why full automation of testing is not possible, practical, or desirable in Test Automation Snake Oil. qmtest-2.4.1/doc/design/qmtest/test.dtd0000664000076400007640000000133611107032206017371 0ustar stefanstefan qmtest-2.4.1/doc/extending.xml0000664000076400007640000005351211110104303015631 0ustar stefanstefan %entities; ]> Extending QMTest If the built-in functionality provided with QMTest does not serve all of your needs, you can extend QMTest. All extensions to QMTest take the form of Python classes. You can write new test classes, resource classes, or database classes in this way. The contents of the class differ depending on the kind of extension you are creating. For example, the methods that a new test class must implement are different from those that must be provided by a new database class. In each case, however, you must create the class and place it in a location where QMTest can find it. The following sections explain how to create extension classes. The last section in this chapter explains how to register your new extension classes.
Extension Classes All extensions to QMTest are implemented by writing a new Python class. This new Python class will be derived from an appropriate existing QMTest Python class. For example, new test classes are derived from Test while new test database classes are derived from Database. The classes from which new extensions are derived (like Test) are all themselves derived from &extension_class;. The Extension class provides the basic framework used by all extension classes. In particular, every instance of Extension can be represented in XML format in persistent storage. Every Extension class has an associated list of parameter attributes. When an Extension instance is written out as XML, the value of each parameter is encoded in the output. Similarly, when an Extension instance is read back in, the parameter values are decoded. Conceptually, two Extension instances are the same if they are instances of the same derived class and their parameters have the same values. Each parameter has a type. For example, every Test has a parameter called target_group. The target group is a string indicating on which targets a particular test should be run. Each parameter is represented by an instance of &field_class;. A Field instance can read or write values in XML format. A Field can also produce an HTML representation of a value, or an HTML form that allows a user to update the value of the field. It is the fact that all Extension parameters are instances of Field that makes it possible to represent Extension instances as XML. Smilarly, it is the use of the Field class that allows the user to edit tests in the QMTest GUI. Each class derived from Extension may contain attributes that are instances of Field. For example, after the following class definitions: class A(Extension): x = TextField() class B(A): y = IntegerField(default_value = 42) z = TextField(default_value = "a value") A has one parameter (x) and B has three parameters (x, y, and z). During construction of extensions you may provide arguments to set the values of these parameters (and thus overriding default values): a = A(x = "argument") b = B(x = "another argument", z = "value") The serialized form of A will be equivalent to argument ]]> and for B another argument 42 value ]]> Extension instances hold appropriately typed attributes for all fields. A TextField translates to a str instance, while a IntegerField translates to an int, etc. > a = A(x = "argument") > print type(a.x), a.x <type 'str'> argument
Field Classes &field_class; instances are used to represent extension parameters. A Field can read and write XML representations of values, generate HTML representations of values, or present HTML forms that permit the user to update the value of the field. There are several classes derived from Field that you can use in extension classes. If none of those classes satisfy your needs, you can create a new class derived from Field. A Field may have a title, which is used when presenting the Field to the user. The title need not be a valid Python identifier. For example, the RSHTarget class has a host parameter whose title is Remote Host Name. When accessing an instance of this class, the programmer refers to self.host. In the GUI, however, the user will see the value presented as Remote Host Name. A Field may have an associated description, which is a longer explanation of the Field and its purpose. This information is presented to the user by the GUI. A Field may have a default value. The default value is used if no argument is provided for the field when the extension is initialized. This example code from RSHTarget shows how a Field is constructed: See the internal documentation for &field_class; for complete interface documentation.
Built-In Field Classes QMTest comes with several useful field classes: &integer_field_class; stores integers. &text_field_class; stores strings. &enumeration_field_class; stores one of a set of (statically determined) possible values. &choice_field_class; stores one of a set of (dynamically determined) possible values. &boolean_field_class; stores a boolean value. &time_field_class; stores a date and time. &attachment_field_class; stores arbitrary data. &set_field_class; stores multiple values of the same type. &tuple_field_class; stores a fixed number of other fields.
Writing Field Classes Before writing any code, you should decide what kind of data your field class will store. For example, will your field class store arbitrary strings? Or only strings that match a particular regular expression? Or will your field class store images? Once you have decided this question, you can write the Validate function for your field class. This function checks an input value (a Python object) for validity. Validate can return a modified version of the value. For example, if the field stores strings, you could choose to accept an integer as an input to Validate and convert the integer to a string before returning it. The FormatValueAsHtml function produces an HTML representation of the value. You must define this function so that the GUI can display the value of the field. The style parameter indicates how the value should be displayed. If the style is new or edit, the HTML representation returned should be a form that the user can use to set the value. If the user does not modify the form, ParseFormValue should yield the value that was provided to FormatValueAsHtml. The MakeDomNodeForValue and GetValueFromDomNode functions convert values to and from XML format. The FormatValueAsText and ParseTextValue functions convert to and from plain text. As with FormatValueAsHtml and ParseFormValue, these pairs of functions should be inverses of one another. The ParseTextValue, ParseFormValue, and GetValueFromDomNode functions should use Validate to check that the values produced are permitted by the Field. In this way, derived classes that want to restrict the set of valid values, but are otherwise content to use the base class functionality, need only provide a new implementation of Validate. All of the functions which read and write Field values may raise exceptions if they cannot complete their tasks. The caller of the Field is responsible for handling the exception if it occurs.
Writing Test Classes If the test classes that come with QMTest do not serve your needs, you can write a new test class. A test class is a Python class derived from &test_class;, which itself is derived from Extension. It may define parameters as discussed in . The test class must provide a Run method that implements the way the test is performed and results are validated. For example, if you want to test that a compiler correctly compiled a particular source file, the source file would be an argument to the test while the Run method would be responsible for running the compiler and the program generated by the compiler. The path to the compiler itself would be provided via the context ( ); that is an input to the testing system that varies depending on the user's environment. The Run method takes two arguments: the context and the result. The context object is an instance of &context_class;. The result object is an instance of &result_class;. The result is initialized with the PASS outcome. Therefore, if the Run method does not modify the result, the test will pass. If the test fails, the Result.Fail method should be called to indicate failure. The Result.Annotate method can be used to add information to the Result, whether or not the test passes. For example, annotations can be used to record the time a test took to execute, or to log the output from a command run as part of the test. Every annotation is a key/value pair. Both keys and values are strings. The key created by a test class C should have the form C.key_name. The value must be valid HTML. When results are displayed in the GUI, the HTML is presented directly to the user. When results are displayed as text, the HTML is converted to plain text. That conversion uses textual devices (such as single quotes around verbatim text) to emulate the HTML markup where possible. As a convenience, you can use Python's dictionary notation to access annotations. For example: is equivalent to: The context (like the result) is a set of key/value pairs. The keys used by a test class C should have the form C.key_name. The values are generally strings, but if a test depends on a resource, the resource can provide context values that are not strings. If the Run raises an unhandled exception, &qmtest; creates a result for the test with the outcome ERROR. Therefore, test classes should be designed so that they do not raise unhandled exceptions when a test fails. However, QMTest handles the exception generated by the use of non-existant context variables specially. Because this situation generally indicates incorrect usage of the test suite, QMTest uses a special error message that instructs the user to supply a value for the context variable.
Writing Resource Classes Writing resource classes is similar to writing test classes. The requirements are the same except that, instead of a Run method, you must provide two methods named SetUp and CleanUp. The SetUp method must have the same signature as a test classs Run. The CleanUp method is similar, but does not take a context parameter. The SetUp method may add additional properties to the context by assigning to its context parameter. These additional properties will be visible only to tests that require this resource. The example below shows the SetUp and CleanUp from the standard QMTest TempDirectoryResource class. This resource creates a temporary directory for use by the tests that depend on the resource. The SetUp method creates the temporary directory and records the path to the temporary directory in the context so that tests know where to find the directory. The CleanUp method removes the temporary directory.
Writing Database Classes The test database class controls the format in which tests are stored. &qmtest;'s default database class stores each test as an XML file, but you might want to use a format that is particularly well suited to your application domain or to your organization's arrangement of computing resources. For example, if you were testing a compiler, you might want to represent tests as source files with special embedded comments indicating what errors are expected when compiling the test. You could write a test database class that can read and write tests in that format. Or, if you wanted to share a single test database with many people in such a way that everyone automatically saw updates to the database, you might want to put all of the tests on a central HTTP server. You could write a test database class that retrieves tests from the server and creates new tests by uploading them to the server. A test database class is a Python class that is derived from &database_class;, which is itself derived from Extension. To create a new database class, you must define methods that read and write Extension instances. The database is also responsible for determining how tests (and other entities stored in the database) are named. Each item stored in the database must have a unique name. For a database that stores files in the filesystem, the name of the file may be a good name. For a database of unit tests for Python module, the name of the module might be a good name for the tests. Choosing the naming convention appropriate requires understanding both the application domain and the way in which the tests will actually be stored. The database class must have a GetExtension method which retrieves an instance of Extension given the name of the instance. If your database is modifiable, you must also provide WriteExtension and RemoveExtension methods. For historical reasons, your database class must also set the class variable _is_generic_database to true.
Registering and Distributing Extension Classes To use your Extension class, you must place the Python module file containing it in a directory where &qmtest; can find it. QMTest searches for extensions in particular places, in the following order: in the paths contained in the QMTEST_CLASS_PATH environment variable. in the class-path associated with a particular test database (typically the QMTest/ subdirectory). in the site-extension path associated with a particular QMTest installation. in the set of built-in extensions that come with a particular QMTest installation. You should generally place module files containing extension classes in the test database's QMTest directory, unless you plan to use the test classes in more than one test database. You must use the qmtest register command to register your new extension class. You must perform this step no matter where you place the module containing your extension class. You can refer to the new extension class using the syntax module.Class, where module is the name of the module and Class is the name of the class. To make your extension classes sharable by other test database instances, you should install them into the site-extension path associated with a qmtest installation. To facilitate this installation, QMTest provides code that can be used in conjunction with python's distutils to install, and even distribute them. The following setup.py script will allow you to install (and even package !) all extension modules from the extensions subdirectory: from qm.dist.distribution import Distribution from distutils.core import setup setup(distclass=Distribution, qmtest_extensions="extensions") Then, the following command installs extension modules from extensions: > python setup.py install
qmtest-2.4.1/doc/concepts.xml0000664000076400007640000010712311110104311015457 0ustar stefanstefan %entities; ]> <application>QMTest</application> Concepts This section presents the concepts that underlie QMTest's design. By understanding these concepts, you will be able to better understand how QMTest works. In addition, you will find it easier to extend QMTest to new application domains. The central principle underlying the design of QMTest is that the problem of testing can be divided into a domain-dependent problem and a domain-independent problem. The domain-dependent problem is deciding what to test and how to test it. For example, should a database be tested by performing unit tests on the C code that makes up the database, or by performing integration tests using SQL queries? How should the output of a query asking for a set of records be compared to expected output? Does the order in which records are presented matter? These are questions that only someone who understands the application domain can answer. The domain-independent part of the problem is managing the creation of tests, executing the tests, and displaying the results for users. For example, how does a user create a new test? How are tests stored? Should failing tests be reported to the user, even if the failure was expected? These questions are independent of the application domain; they are just as relevant for compiler tests as they are for database tests. QMTest is intended to solve the domain-independent part of the problem and to offer a convenient, powerful, and flexible interface for solving the domain-dependent problem. QMTest is both a complete application, in that it can be used out of the box to handle many testing domains, and infrastructure, in that it can be extended to handle other domains. Throughout this chapter we will use the qmtest application with a variety of parameters and options. For a full description of the qmtest please refer to the command-line reference. The following commands create a simple test database in the current working directory. This test database will be used throughout the following sections of this tutorial. > mkdir tdb > cd tdb > qmtest create-tdb
Tests A test checks for the correct behavior of the target application. What constitutes correct behavior will vary depending on the application domain. For example, correct behavior for a database might mean that it is able to retrieve records correctly while correct behavior for a compiler might mean that it generates correct object code from input source code. Every test has a name that uniquely identifies the test, within a given test database. Test names must be composed entirely of lowercase letters, numbers, the _ character, and the . character. You can think of test names like file names. The . character takes the place of /; it allows you to place a test in a particular directory. For example, the test name a.b.c names a test named c in the directory a.b. The directory a.b is a subdirectory of the directory a. Every test is an instance of some test class. The test class dictates how the test is run, what constitutes success, and what constitutes failure. For example, the command.ExecTest class that comes with QMTest executes the target application and looks at its output. The test passes if the actual output exactly matches the expected output. The arguments to the test parameterize the test; they are what make two instances of the same test class different from each other. For example, the arguments to command.ExecTest indicate which application to run, what command-line arguments to provide, and what output is expected. The python.ExecTest class is similar to command.ExecTest, but, instead of executing a command using the system shell, it evaluates an expression in the Python programming language. The test passes if (and only if) the expression is true. In Python, the expressions True and False are literals. The following creates two trivial tests, python_pass and python_fail: > qmtest create --id=python_pass -a expression='True' test python.ExecTest > qmtest create --id=python_fail -a expression='False' test python.ExecTest The first test will always pass while the second will always fail. The qmtest ls command will show the content of the test database: > qmtest ls python_fail python_pass Similar to the Unix ls command, the option can be used to provide a detailed listing, with kind ("test", "resource", or "suite"), extension class, and id: > qmtest ls -l test python.ExecTest python_fail test python.ExecTest python_pass
Running Tests To run one or more tests, use the qmtest run command: > qmtest run Each invocation of the qmtest run command is a single test run, and produces a single set of test results and statistics. Specify as arguments the names of tests and test suites to run. Even if you specify a test more than once, either directly or by incorporation in a test suite, QMTest runs it only once. If you wish to run all tests in the test database, use the implicit test suite . (a single period; see ), or omit all IDs from the command line. QMTest can run tests in multiple concurrent threads of execution or on multiple remote hosts. See the documentation for the run command for details. How the output of the qmtest run command should be interpreted will be discussed in .
Prerequisite Tests QMTest can avoid running one test (a "dependent test") when some other test (a "prerequisite test") has a particular outcome. Suppose that you have a test database with a very simple test that can be run very quickly, and a very complex test that takes hours to run. You know that if the simple test fails, then there is no chance that the complex test will pass. In that case, you could make the simple test a prerequisite of the complex test. Then, when you run both tests, QMTest will run the simple test first. If it fails, the complex test will not be run at all. Alternatively, suppose that you have a very comprehensive test that tests ten features of your software. You also have ten separate tests, one for each feature. The comprehensive test can be run in one minute; runnning the separate tests takes two minutes each. So, you want to run the comprehensive test first; if it passes, there is no need to run the individual tests. However, if the comprehensive test fails, you may want to run the single tests to isolate the problem. In this case, each of the simple tests would have the comprehensive test as a prerequisite, indicating that the simple test should be run only if the comprehensive test fails. If you explicitly run just the dependent test, QMTest will not run the prerequisite test automatically. In other words, prerequisites are an optimization; when running both the prerequisite and the dependent test, QMTest will run them in the order you've implied, and can omit the dependent test if it is not useful. But, QMTest will not automatically force you to run the prerequisite tests when you only want to run the dependent test. Because prerequisite tests are not run unless you ask for them, the dependent test should not depend in any way on the prerequisite test. Otherwise, users will see different test outcomes when they run the dependent test by itself. In other words, each test should stand alone; the order in which tests are run should not affect their outcomes.
Ordering and Dependencies Given one or more input test names and test suite names, QMTest employs the following procedure to determine which tests and resources to run and the order in which they are run. QMTest resolves test names and test suite names. Test suites are expanded into the tests they contain. Since test suites may contain other test suites, this process is repeated until all test suites have been expanded. The result is a set of tests that are to be run. QMTest computes a schedule for running the tests to be run such that a test's prerequisites are run before the test itself is run. Prerequisites not included in the test run are ignored. Outside of this condition, the order in which tests are run is undefined. If QMTest is invoked to run tests in parallel or distributed across several targets, the tests are distributed among them as well. QMTest does not guarantee that a test's prerequisites are run on the same target, though. On each target, tests are assigned to the next available concurrent process or thread. QMTest determines the required resources for the tests to be run. If several tests require the same resource, QMTest attempts to run all of the tests on the same target. In this case, the resource is set up and cleaned up only once. In some cases, QMTest may schedule the tests on multiple targets; in that case, the resource is set up and cleaned up once on each target. In the following cases, a test or resource will not be executed, even though it is included in the set of tests enumerated above: A test specifies for each of its prerequisite tests an expected outcome. If the prerequisite is included in the test run and the actual outcome of the prerequisite test is different from the expected outcome, the test is not run. Instead, it is given an UNTESTED outcome. If a test's prerequisite is not included in the test run, that prerequisite is ignored. If a setup function for one of the resources required by a test fails, the test is given an UNTESTED outcome. The cleanup function of a resource is run after the last test that requires that resource, whether or not that test was run. The cleanup function is run even if the setup function failed.
Test Results A result is an outcome together with some annotations. The outcome indicates whether the test passed or failed. The annotations give additional information about the result, such as the manner in which the test failed, the output the test produced, or the amount of time it took to run the test.
Outcomes The outcome of a test indicates whether it passed or failed, or whether some exceptional event occurred. There are four test outcomes: PASS: The test succeeded. FAIL: The test failed. ERROR: A problem occurred in the test execution environment, rather than in the tested system. For example, this outcome is used when the test class attempted to run an executable in order to test it, but could not because the system call to create a new process failed. This outcome may also indicate a defect in QMTest or in the test class. UNTESTED: QMTest did not attempt to execute the test. For example, this outcome is used when QMTest determines that a prerequisite test failed. Thus, running QMTest with the two previously defined tests will result in the following output: > qmtest run ... --- TEST RESULTS ------------------------------------------------------------- python_fail : FAIL Expression evaluates to false. python_pass : PASS ... --- STATISTICS --------------------------------------------------------------- 2 tests total 1 ( 50%) tests FAIL 1 ( 50%) tests PASS In addition, the results are stored in a results file (results.qmr by default).
Annotations An annotation is a key/value pair. Both the keys and values are strings. The value is HTML. When a test (or resource) runs it may add annotations to the result. These annotations are displayed by QMTest and preserved in the results file. If you write your own test class, you can use annotations to store information that will make your test class more informative.
Expected Outcomes The easiest way to create expectations is to tell QMTest that you expect future results to be the same as the results you just obtained. Thus, QMTest accepts result files obtained from prior test runs as expectations. Thus, rerunning QMTest, but using results.qmr as expectations, the test results are displayed differently: > qmtest run -O results.qmr ... --- TEST RESULTS ------------------------------------------------------------- python_fail : XFAIL Expression evaluates to false. python_pass : PASS ... --- TESTS WITH UNEXPECTED OUTCOMES ------------------------------------------- None. --- STATISTICS --------------------------------------------------------------- 2 (100%) tests as expected
Test Suites A test suite is a collection of tests. QMTest can run an entire test suite at once, so by grouping tests together in a test suite, you make it easier to run a number of tests at once. A single test can be a member of more than one test suite. A test suite can contain other test suites; the total set of tests in a test suite includes both those tests included directly and those tests included as part of another test suite. Every test suite has a name, following the same conventions given above for tests. One use of test suites is to provide groups of tests that are run in different situations. For example, the nightly test suite might consist of those tests that should be run automatically every night, while the checkin test suite might consist of those tests that have to pass before any changes are made to the target application.
Implicit Test Suites explains how you may arrange tests in a tree hierarchy, using a period (.) as the path separator in test names. QMTest defines an implicit test suite for each directory. The name of these implicit test suites is the same as the name of the directory. The implicit test suite corresponding to a directory contains all tests in that directory or its subdirectories. Let us create some more tests, but this time within their respective subdirectories: > qmtest create --id=dir1.one -a expression='True' test python.ExecTest > qmtest create --id=dir1.two -a expression='False' test python.ExecTest > qmtest create --id=dir2.one -a expression='True' test python.ExecTest > qmtest create --id=dir2.dir3.one -a expression='False' test python.ExecTest > qmtest create --id=dir2.dir3.two -a expression='False' test python.ExecTest This will create five new tests, together with three directories: > qmtest ls -lR directory dir1 test python.ExecTest dir1.one test python.ExecTest dir1.two directory dir2 directory dir2.dir3 test python.ExecTest dir2.dir3.one test python.ExecTest dir2.dir3.two test python.ExecTest dir2.one These directories are implicit suites, i.e. it is possible to only address tests within them: > qmtest ls -lR dir2 directory dir2 directory dir2.dir3 test python.ExecTest dir2.dir3.one test python.ExecTest dir2.dir3.two test python.ExecTest dir2.one The suite named "." (a single period) is the implicit test suite corresponding to the root directory in the test database. This suite therefore contains all tests in the database. For example, the command > qmtest run . is equivalent to: > qmtest run Both commands run all tests in the database.
Explicit Test Suites Explicit test suites are a means to refer to a set of tests for the purpose of executing them together, no matter how they are organized in the test database. For example, you may want to run a subset of all tests nightly. To do this, you create a suite, listing all tests (as well as contained suites) explicitely: > qmtest create --id=nightly suite explicit_suite.ExplicitSuite(test_ids="['dir1.one', 'dir2.one']", suite_ids="['dir2.dir3']") > qmtest ls -l directory dir1 directory dir2 suite explicit_suite.ExplicitSuite nightly > qmtest ls -l nightly test python.ExecTest dir1.one directory dir2.dir3 test python.ExecTest dir2.one
Test Database A test database stores tests, test suites, and other entities. When you ask QMTest for a particular test by name, it queries the test database to obtain the test itself. QMTest stores a test database in a single directory, which may include many files and subdirectories. In general, QMTest can only use one test database at a time. However, it is possible to create a test database which contains other test databases. This mechanism allows you to store the tests associated with different parts of a large application in different test databases, and still combine them into a single large test database when required. A single test database can store many different kinds of tests. By default, QMTest stores tests, test suites, and all other entities in the test database using subdirectories containing XML files. Generally, there should be no need to examine or modify these files directly. However, the use of an XML format makes it easy for you to automatically generate tests from another program, if required.
Expectation Database While typically tests are expected to pass, it sometimes is meaningful to indicate a different expectation. QMTest represents expectations by results. Here, the outcomes represent the expectated outcome, and the annotations may explain the expectation. An expectation database stores expectations associated with a test database. It provides an interface to query expectations by test id. In the simplest case all tests are expected to pass. In a slightly less simple case, an existing set of results, obtained from a previous test run, may be used as expectations for a subsequent test run.
Context When you create a test, you choose arguments for the test. The test class uses this information to run the test. However, the test class may sometimes need information that is not available when the test is created. For example, if you are writing compiler tests to verify conformance with the C programming language specification, you do not know the location of the C compiler itself. The C compiler may be installed in different locations on different machines. A context gives users a way of conveying this kind of information to tests. The context is a set of key/value pairs. The keys are always strings. The values of all context properties provided by the user are strings. In general, all tests in a given use of QMTest will have the same context. However, when a resource is set up, it may place additional information in the context of those tests that depend upon it. The values inserted by the resource may have any type, so long as they can be "pickled" by Python. All context properties whose names begin with "qmtest." are reserved for use by QMTest. The values inserted by QMTest may have any type. Test and resource classes should not depend on the presence or absence of these properites. To understand how a context is used during the execution of a test let us start by creating a somewhat less trivial test: > qmtest create --id compile test compilation_test.CompilationTest(executable="compile", source_files="['/path/to/compile.cc']")" When run, this test will compile /path/to/compile.cc and run the resulting executable. The test passes if compilation succeeds, and the program exit status indicates success. The compilation_test.CompilationTest test class requires that the compiler be available in the context with the key CompilationTest.compiler_path. You can provide a context variable to QMTest either through a context file or on the command-line using the -c option. For example: > qmtest run -c CompilationTest.compiler_path=g++ compile will run the test using the g++ compiler, while: > qmtest run -c CompilationTest.compiler_path=/bin/CC compile will run the test with the /bin/CC compiler.
Resources Some tests take a lot of work to set up. For example, a database test that checks the result of SQL queries may require that the database first be populated with a substantial number of records. If there are many tests that all use the same set of records, it would be wasteful to set up the database for each test. It would be more efficient to set up the database once, run all of the tests, and then remove the databases upon completion. You can use a resource to gain this efficiency. If a test depends on a resource, QMTest will ensure that the resource is available before the test runs. Once all tests that depend on the resource have been run QMTest will destroy the resource. Just as every test is an instance of a test class, every resource is an instance of a resource class. The resource class explains how to set up the resource and how to clean up when it is no longer needed. The arguments to the resource class are what make two instances of the same resource class different from each other. For example, in the case of a resource that sets up a database, the records to place in the database might be given as arguments. Every resource has a name, using the same format that is used for tests. Under some circumstances (such as running tests on multiple targets at once), QMTest may create more than one instance of the same resource. Therefore, you should never depend on there being only one instance of a resource. In addition, if you have asked QMTest to run tests concurrently, two tests may access the same resource at the same time. You can, however, be assured that there will be only one instance of a particular resource on a particular target at any one time. Tests have limited access to the resources on which they depend. A resource may place additional information into the context () that is visible to the test. However, the actual resource object itself is not available to tests. (The reason for this limitiation is that for a target consisting of multiple processes, the resource object may not be located in the same process as the test that depends upon it.) Setting up or cleaning up a resource produces a result, just like those produced for tests. QMTest will display these results in its summary output and record them in the results file. Building on the previous example of a CompilationTest, let us consider a situation where some test application should be run multiple times with different arguments. The test application, however, needs to be compiled first. In order to avoid recompiling the application for each test, you can create a resource that compiles the application once. Then, tests that depend on this resource can assume that the application has already been built. The following commands: > qmtest create --id applet resource compilation_test.CompiledResource(executable="applet", source_files="['/path/to/applet.cc']") > qmtest create --id run_applet_0 test compilation_test.ExecutableTest(args="['0']", resources="['applet']") > qmtest create --id run_applet_1 test compilation_test.ExecutableTest(args="['1']", resources="['applet']") create a resource (named "applet") for the application and two tests ("run_applet_0" and "run_applet_1"), both of which make use of "applet", but which pass it different command-line options. > qmtest run -c CompilationTest.compiler_path=g++ run_applet_0 run_applet_1 --- TEST RESULTS ------------------------------------------------------------- Setup applet : PASS run_applet_0 : PASS run_applet_1 : PASS Cleanup applet : PASS
Targets A target is QMTest's abstraction of a machine. By using multiple targets, you can run your tests on multiple machines at once. If you have many tests, and many machines, you can greatly reduce the amount of time it takes to run all of your tests by distributing the tests across multiple targets. By default, QMTest uses only one target: the machine on which you are running QMTest. You may specify other targets by creating a target file, which lists the available targets and their attributes, and specifying the target file when you invoke qmtest. Each target is a member of a single target group. All targets in the same target group are considered equivalent. A target group is specified by a string. If you are testing software on multiple platforms at once, the target group might correspond to machines running the same operating system. For example, all Intel 80386 compatible machines running GNU/Linux might be in the i386-pc-linux-gnu target group. QMTest by default executes all tests using a 'serial target', i.e. one after another. This behavior can be changed by specifying a different concurrency strategy, such as one that uses multiple threads, multiple processes, or even multiple physical machines. > qmtest create-target -a name=local -a group=local -a threads=2 a thread_target.ThreadTarget This creates a 'thread target' where two threads are used to run the tests in parallel.
Hosts Sometime it is necessary to execute a test application on a different machine than the one running the qmtest application itself. For example, if the test involves executing an application previously cross-compiled, the binary needs to be uploaded to an appropriate host and run there. QMTest provides a host abstraction for this purpose. To use this mechanism, test classes need to provide explicit support for it. A number of built-in test classes support cross-testing. To run the compile test on a remote target machine, specify a CompilationTest.target variable in the context file to contain a host descriptor: CompilationTest.compiler=/path/to/cross_compiler CompilationTest.target=ssh_host.SSHHost(host_name="192.168.0.100") This will run the compiled executable on the machine with the IP address 192.168.0.100, using ssh for communication.
qmtest-2.4.1/doc/fo.xsl0000664000076400007640000001515411107032207014267 0ustar stefanstefan 8pt 18pt 12pt 10pt 1.5in 1.5in titlepage-even titlepage-odd body-even body-odd 1 1 1 1 0.5in 0.5in Chapter no qmtest-2.4.1/doc/cs.css0000664000076400007640000000226611107032207014252 0ustar stefanstefan/********* Headings *********/ h1, h2, h3 { font-family: Verdana, Arial, Helvetica, sans-serif; font-weight: bold; margin-top: 2px; padding-top: 2px; } h1 { font-size: 14px; color: #111111; margin-bottom: 0px; padding-bottom: 0px; text-transform: capitalize; } h2 { font-size: 11px; color: #222222; margin-bottom: 2px; padding-bottom: 2px; text-transform: capitalize; } h3 { font-size: 10px; color: #333333; font-style: italic; margin-top: 3px; margin-bottom: 3px; padding-top: 3px; padding-bottom: 3px; } /*@import url("http://www.codesourcery.com/codesourcerystyles.css");*/ body { /* The CodeSourcery stylesheet sets the margin for the body to 0px, but here we do not have the same graphical elements. */ margin: 8px; } pre.programlisting, pre.screen { font-size: smaller; border: 1px solid #aaaaaa; background-color: #eeeeee; margin: 20px; padding: 10px; } /* This is the same style used for ".code" in the CodeSourcery stylesheet. */ .guibutton,.guimenu,.guisubmenu,.guimenuitem { font-family: "Courier New", Courier, mono; font-size: 11px; line-height: 15px; color: #000000; } .remark { color: #ff0000; } qmtest-2.4.1/doc/qm.css0000664000076400007640000001054011107032207014254 0ustar stefanstefan/*********************************************************************** File: qm.css Author: Alex Samuel Date: 2000-10-20 Contents: Main style sheet for qm documentation. Copyright (C) 2000 CodeSourcery LLC For license terms see the file COPYING. ***********************************************************************/ /* Headings. Use

...

for titles.

...

for subtitles.

...

for chapter headings.

...

for section headings.
...
for subsection headings.
...
for subsubsection headings. */ /* Document body. */ body { margin-left: 10%; margin-right: 10%; color: black; background: white; } /* Table of contents. Place table of contents inside
...
. */ div.Contents { background-color: #ffffcc; color: black; border: none; border-width: thin; width: 100%; padding: 1ex; } /* Definitions. */ /* Use ... for the primary definition of a term or concept. Do not set the name attribute; this is done automatically by XHTML processing.*/ a.TermDef { color: #000060; background-color: white; font-style: italic; } /* Use ... for subsequent uses of a defined term or concept. Do not set the ref attribute; this is done automatically by the XHTML processing. But be sure to use exactly the same spelling of the term. */ a.Term:link, a.Term:visited { color: #000060; background-color: white; text-decoration: none; } a.Term:active, a.Term:hover { color: #000060; background-color: white; text-decoration: underline; } /* Source code and such. */ /* Use ... for other source code. */ code { } /* Use
...
when presenting official public APIs. */ div.API { background-color: #f0e0ff; border: none; padding: 1ex; } /* Use
...
when presenting XML samples. */ div.XML { background-color: #e0f0ff; border: none; padding: 1 ex; } /* Use ... for identifiers and other names used in source code. */ span.Identifier { font-family: courier, monospace; font-weight: bold; } /* Use ... for the name of a class. */ span.Class { font-family: courier, monospace; font-weight: bold; } /* Use ... for function names. */ span.Function { font-family: courier, monospace; font-weight: bold; } /* Table formatting. */ /* General tables, containing primarily text. */ table { border-style: none; padding: 4pt; } /* A heading row in a table. */ tr.Heading { background-color: black; color: white; font-weight: bold; } /* Miscellaneous editorial stuff. */ /* Use ... as a marker for material that needs to be revisited, revised, or completed. */ span.Fixme { background-color: white; color: red; } /*********************************************************************** CodeSourcery Styles ***********************************************************************/ /*** The styles below this point are taken from: http://www.codesourcery.com/codesourcerystyles.css ***/ h1 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; font-weight: bold; color: #757c96; } h1 { margin-top: 2px; margin-bottom: 0px; padding-top: 2px; padding-bottom: 0px; } h2 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; font-style: normal; font-weight: bold; font-variant: normal; text-transform: capitalize; color: #333333; margin-top: 2px; margin-bottom: 2px; padding-top: 2px; padding-bottom: 2px; } h3 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 10px; font-weight: normal; color: #000000; font-style: italic; margin-top: 3px; margin-bottom: 3px; padding-top: 3px; padding-bottom: 3px; } a:hover { color: #bdaa7a; } a { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11px; line-height: 16px; font-weight: normal; color: #3050c0; text-decoration: none; } .code,.filename,.command,.symbol,.literal,.userinput,.screen,.classname,.property { font-family: "Courier New", Courier, mono; font-size: small; font-weight: normal; text-transform: none; } qmtest-2.4.1/doc/qmtest.ent~0000664000076400007640000000507511107032207015357 0ustar stefanstefan QM"> QMTest"> QMTest"> QM"> Context"> Result"> Extension"> Field"> IntegerField"> TextField"> EnumerationField"> ChoiceField"> BooleanField"> TimeField"> AttachmentField"> SetField"> TupleField"> Test"> Database"> TestDescriptor"> qmtest-2.4.1/doc/qmtest.ent0000664000076400007640000000510511111010414015142 0ustar stefanstefan QM"> QMTest"> QMTest"> QM"> Context"> Result"> Extension"> Field"> IntegerField"> TextField"> EnumerationField"> ChoiceField"> BooleanField"> TimeField"> AttachmentField"> SetField"> TupleField"> Test"> Database"> TestDescriptor"> qmtest-2.4.1/doc/graphics/0000775000076400007640000000000011122067201014724 5ustar stefanstefanqmtest-2.4.1/doc/graphics/csl-logo.pdf0000775000076400007640000003620111107032203017140 0ustar stefanstefan%PDF-1.4 % 6 0 obj <> endobj xref 6 16 0000000016 00000 n 0000000765 00000 n 0000000616 00000 n 0000000841 00000 n 0000001016 00000 n 0000001101 00000 n 0000001135 00000 n 0000002109 00000 n 0000003140 00000 n 0000004110 00000 n 0000005134 00000 n 0000006110 00000 n 0000007100 00000 n 0000008076 00000 n 0000008989 00000 n 0000011658 00000 n trailer <]>> startxref 0 %%EOF 8 0 obj<>stream xb``e``Z Y8xA1Y^g˛iL#fb @ endstream endobj 7 0 obj<> endobj 9 0 obj<> endobj 10 0 obj<>/ProcSet[/PDF]/ExtGState<>>> endobj 11 0 obj[/ICCBased 20 0 R] endobj 12 0 obj<>stream HU=dE ߯ptnt !Ɇh4K2 =U~KOBm[&ۖ!ݎ!am^2!Gbeedtqot<6r9hx~h2b >SFS.a󡷝BtSV7Rm V,ţx9#18F \\, -F?/ra!V<3`eþxo2a-mt"` 7,g֢i)-`NYLߴwEu&4~4xp">Q#weOW~S>O?w`(ݿJY'A+/;NO!h '_]Ee!!A:BYүJfn>;I\mp{=2u]H*0xˠEuRM5!ͬa!H(~6a+q_f**lBJ pLݏbX'KΓKX6h- MlX UCB6g1X%w^BzN E :]^Y">A~Qr!FxkJjzxa`Fm\U}?()ԣ__C@~wn@[AEI@+Y&s/m"cryF>m5q=IPB*%%cj&d楤hgE\0{׍ Zb ˑA NO˰֦:}!\mր),& 8kœ@ 9y8t6O^K[Ii`NK~') 튻NmJsUĴ>!0 endstream endobj 13 0 obj<>stream HT;0 D9b,9TfټDt].DF U,RdX%:T [dIt&culώӴ&b)z3ֆQq@HWtm'PL$)${3X|ȌASV_#=N>Y|1%rQ|֑`5W$p<~yUڗv䮭zmF|Hh]M؛w˅7=1@2Hcsyi*^c!CCƵ'bol9y+blYI}%K7XƧe_}~zl c W ucCwP -(a$rimR&bmFKX0GӍKf89[K YgIIsR0%e5%Kj{l3'pі>cansX鍻Kk2mKJ8 Ĵ"M <9b1R=rw o~e|j&)OG#GN5naVoAWR@,!bi$LzY^* ztǭrp_@ˍ!6GqZ$E*m*`ELB)bBݚ7g{܅c9'^V;pjǁ&QCH6Ēazqne}[8_IJϮ5z.E5DA0t ^Ԣzeٓnէ?v8*o(Cܨx36S.ؼ]}@ ǐsԆ*13`VrcٔJM~׫62E(A^B࠵at>EȣmFIilel3p_{&k|8{H*O~3_0JU̗9nnb}][=bhEaH8{;[3֛^bz`V endstream endobj 14 0 obj<>stream HLU1+&vI=rtݠsyd{=zL{2G)D+c*Fe2Ywm u"ԻдG\ 2r}]u]aq|D=9-eBs" ח R6{\ ( "/h:#;"cE:!$sL%;U/з蹁no-"W ;e?l)Dw8R{]QcBVKo|>h{)x'PJFd.+kP(l]6O2/PeQsHF[A3'{JeN]:8đ}p(񂒅ay6gA" MY}@C8>:%6K! @xy?"+5F}raMoqn\A-Zf#Zcr$LOd VBMpk96_]+?ahVInvi ))bʑΧ]N3.DJ{cwskB4+ JoW0x?BbjjKGOE;B`%.m|][+ [zÕ";;ƺ^0O!U*LRT謵-e.nrW [%)6}ݝC aU>z ϼflht۵KbD2|1i_5.Epܞ>TQ2;tajN$5u;o$?w F5R~8fe:% yeWWJQޫX^wBcl?ޒ endstream endobj 15 0 obj<>stream HTU˒$) Wy~`Lv:MVdH%<>H⯌IZho!ry~KTsL;s,l=ȱ=lqtQot$^˞Uޔ6)wW,/z?5!vfQkwCBSeϗUq;i9a5=_~B2}nQ2@+6vj@_Էi'}tՊ^Pa0Jve30)n_F7i@.e8\a:ѡ#0EYBaLFg &3sHmisbÉՕDH).r4qJ5 KVe s}.S8` H*%F[(:(1b(`8i  ޢIYu e:h @ݺκ]51.U=cҦS+mZ*cY֓&R;fz/E%KQkl? gSGD*D Jy`E !X ξƾxA}v!n ӣh]n\| 5B:;5_k Zpy_e^@ J=T뭀0:j=͝lV37y0 endstream endobj 16 0 obj<>stream H\V;nd9 7$D`SEul`ERڴi$GܹdF: m?Oy Z._ԣ|} _6Wye 3z$ͯ<)w{Q)щŃ@HH$8%SԢs T![w[u(*;##tzt"ebAP#Zr G\r Bt9MH>stream HL;rd1Es$>Uyνvbϳ#9fȳ2p&%ϣs٥0"f:xX94d'0FBZ>Q m[%PhcEq{)u =?A ڪo w|l(SJ3qVQGjSQu`s>"Ce7ZE5eֳ?2ۜE裪O+|} 5W r u胡| ה0$!CՆgas8AS*DT1 &@f&{f<-x?8kNڜ5*}rX͓ 5(y5mYVHaMz1^@/k`u(vN4+*RX *߆lGk}(*!q5ƌfr} |cCKI@\"<^ֲ^{ڹ\]3¥u"Y[d9kwp=k~.>򪪴d\m5RLE+@c"\ŅMS_scnvo.'t=ʺ!'v}U\{~^P՟ZD<V0XIN8!JM= cHKG[jMC8 VVSV0 ČYFmWUD X6--4apFv2`b6vp qe"Tb]n:$I(fĝ#'=VzBk~99[-PPկO[P@6/b endstream endobj 18 0 obj<>stream H\Vˎ$9Wyyf8Gs*`'硰E.! Άf${ʰ5ڠ~Yh sh;붽)/Āor~se耼r` sy#NJMY?s؍nC,ƾ2l lpgXon! lyS1T\.K(9}eL|4mgzN{mɴ;ѧyOw0s_2BP hnq :T㍅Nu[{9 Qi2VK)hKp9|I C[}Z.G}Z8_yyyЀ?pJ&?~(>_G29FCBO@sut~hpg*m9Yz};SRd1`f:MP7051w4$7A"mAzPDQ疹10owVu5@f PA|7.QexC"O:s{*h JyHz>Kg2)H`a=/@"Z:%F0/a τPYzGZTtېX~hل ҢQu0N0\^exQW`܃Vp8x)?8wsa(af' 񾠮9|PlwJ/G*/z5I],K%؄v6}Wheͥ՜ph8>pxAy(#obF8cx׀eZ ,1Uv !ɽǚ H~3c=ͼɁ~k!d⅖ZvA1;9-S_ gi"}3#K endstream endobj 19 0 obj<>stream HTU9r1 H{\Hn#nMcgg:~ ς j!o(~|dhPjĶb5r Тsq.Gb\[c&=ϐc)Yr>9DZi4tk,r`\2-#~ޛIC)(-.}ZcOݭ,Y:\|~R~!O,k[Cy]Id;T$/]  )#`0gFH֩_]} Aeqog}kc[.}+{TvY]J9ۛEPhKA"EXa4NJo&DE"HE \aP0;ÃkVUd]+S:F{r r_'¢ASpY阬U®hg%m' л&JUN{ OD-Fki]Y#בXE5H{֩E>stream HyTSwoɞc [5laQIBHADED2mtFOE.c}08׎8GNg9w߽'0 ֠Jb  2y.-;!KZ ^i"L0- @8(r;q7Ly&Qq4j|9 V)gB0iW8#8wթ8_٥ʨQQj@&A)/g>'Kt;\ ӥ$պFZUn(4T%)뫔0C&Zi8bxEB;Pӓ̹A om?W= x-[0}y)7ta>jT7@tܛ`q2ʀ&6ZLĄ?_yxg)˔zçLU*uSkSeO4?׸c. R ߁-25 S>ӣVd`rn~Y&+`;A4 A9=-tl`;~p Gp| [`L`< "A YA+Cb(R,*T2B- ꇆnQt}MA0alSx k&^>0|>_',G!"F$H:R!zFQd?r 9\A&G rQ hE]a4zBgE#H *B=0HIpp0MxJ$D1D, VĭKĻYdE"EI2EBGt4MzNr!YK ?%_&#(0J:EAiQ(()ӔWT6U@P+!~mD eԴ!hӦh/']B/ҏӿ?a0nhF!X8܌kc&5S6lIa2cKMA!E#ƒdV(kel }}Cq9 N')].uJr  wG xR^[oƜchg`>b$*~ :Eb~,m,-ݖ,Y¬*6X[ݱF=3뭷Y~dó ti zf6~`{v.Ng#{}}jc1X6fm;'_9 r:8q:˜O:ϸ8uJqnv=MmR 4 n3ܣkGݯz=[==<=GTB(/S,]6*-W:#7*e^YDY}UjAyT`#D="b{ų+ʯ:!kJ4Gmt}uC%K7YVfFY .=b?SƕƩȺy چ k5%4m7lqlioZlG+Zz͹mzy]?uuw|"űNwW&e֥ﺱ*|j5kyݭǯg^ykEklD_p߶7Dmo꿻1ml{Mś nLl<9O[$h՛BdҞ@iءG&vVǥ8nRĩ7u\ЭD-u`ֲK³8%yhYѹJº;.! zpg_XQKFAǿ=ȼ:ɹ8ʷ6˶5̵5͵6ζ7ϸ9к<Ѿ?DINU\dlvۀ܊ݖޢ)߯6DScs 2F[p(@Xr4Pm8Ww)Km endstream endobj 21 0 obj<> endobj 1 0 obj<> endobj 2 0 obj<> endobj 3 0 obj<> endobj 4 0 obj<>stream untitled endstream endobj 5 0 obj<> endobj xref 0 6 0000000000 65535 f 0000011734 00000 n 0000011767 00000 n 0000011790 00000 n 0000011840 00000 n 0000015161 00000 n trailer <> startxref 116 %%EOF qmtest-2.4.1/doc/tutorial.xml0000664000076400007640000000602611110104320015504 0ustar stefanstefan %entities; ]> QMTest: User's Guide CodeSourcery, Inc. 2002-2006 CodeSourcery Inc &license; Version &version; QMTest is a testing tool. You can use QMTest to test a software application, such as a database, compiler, or web browser. You can even QMTest to test a physical system (like a valve or thermometer) if you have a way of connecting it to your computer. Code that has not been tested adequately generally does not work. Yet, many applications are deployed without adequate testing, often with catastrophic results. It is much more costly to find defects at the end of the release cycle than at the beginning. By making it easy to develop tests, and execute those tests to validate the application, QMTest makes it easy to find problems easier, rather than later. QMTest can be extended to handle any application domain and any test format. QMTest works with existing testsuites, no matter how they work or how they are stored. QMTest's open and pluggable architecture supports a wide variety of applications. QMTest features both an intuitive graphical user interface and a conventional command-line interface. QMTest can run tests in serial, in parallel on a single machine, or across a farm of possibly heterogeneous machines. CodeSourcery provides support for QMTest. CodeSourcery can help you install, integrate, and customize QMTest. For more information, visit the QMTest web site. The concepts chapter The customization chapter The extending chapter qmtest-2.4.1/doc/html.xsl0000664000076400007640000000236111107032207014623 0ustar stefanstefan book toc,title,figure,table,example,equation chapter toc,title part toc,title preface toc,title qandadiv toc qandaset toc reference toc,title section toc set toc,title qmtest-2.4.1/doc/process-xhtml.py0000775000076400007640000001171211107032207016314 0ustar stefanstefan#! /usr/bin/python ######################################################################## # # File: process-xhtml.py # Author: Alex Samuel # Date: 2000-10-24 # # Contents: # Processing for XHTML documentation. # # This script is used to generate HTML, suitable for browsing, from # XHTML documentation sources. It performs the following tasks: # # - Any processing that's necessary to make our documentation # compatible with XHTML (which isn't fully supported in all # browsers). # # - Automatic generation of crosslinks from uses to definitions # of terms. # # Usage: # This script reads XHTML from a single files specified on the # command line, and writes processed XHTML to standard output. # # Bugs: # This script, as currently written, is a bit of a hack, but it # should do for a while. # # Copyright (c) 2000 by CodeSourcery, LLC. All rights reserved. # # For license terms see the file COPYING. # ######################################################################## import pickle import re import string import sys # Terms are caches across invocations in this file, allowing # inter-file cross references. terms_filename = '.terms' # Terms are recognized for these classes of the XHTML element. terms_classes = [ 'Term', 'Class', 'API' ] # The same class name with 'Def' appended is taken recognized as the # definition of a term. So, for instance, 'TermDef' is the class for # terminology definitions, and 'Term' for corresponding uses. terms_def_classes = map(lambda klass: klass + 'Def', terms_classes) def to_camel_caps(str): """Converts a string to CamelCaps.""" # Break STR into words. words = string.split(string.strip(str)) # Capitalize each word. words = map(string.capitalize, words) # Join the words together, without spaces among them. return string.join(words, '') def make_label(klass, term): """Returns an HTML label to be used for a term.""" return '%s-%s' % (klass, to_camel_caps(term)) def clean_up_term(term): """Clean up whitespace and such to canonicalize a term.""" return string.strip(re.sub('\s+', ' ', term)) # Load terms from the cache file, if it exists. try: terms_file = open(terms_filename, "r") terms = pickle.load(terms_file) terms_file.close() except: terms = {} # Read input from the specified file. input_file = sys.argv[1] input = open(input_file, 'r').read() input_file = re.sub('\.xhtml', '.html', input_file) # Regular expression for definitions of terms. term_definition_re = re.compile('%s)">' % string.join(terms_def_classes, '|') + '(?P[^<]*)') # Regular expression for uses of terms. term_use_re = re.compile('%s)">' % string.join(terms_classes, '|') + '(?P[^<]*)') # Fix up definitions of terms. while 1: match = term_definition_re.search(input) if match == None: break klass = match.group('class') term = clean_up_term(match.group('term')) label = make_label(klass, term) # Add the name attribute to the anchor element. input = input[ : match.start()] \ + '%s' % (klass, label, term) \ + input[match.end() : ] # Add/update a reference in the terms dictionary. ref = '%s#%s' % (input_file, label) klass = klass[ : -3] if not terms.has_key(klass): terms[klass] = {} klass_dict = terms[klass] klass_dict[term] = ref # Fix up uses of terms. while 1: match = term_use_re.search(input) if match == None: break klass = match.group('class') term = clean_up_term(match.group('term')) # Look up the term in the terms dictionary. if not terms.has_key(klass): terms[klass] = {} klass_dict = terms[klass] if klass_dict.has_key(term): ref = klass_dict[term] # If the term ends with 's', naively assume its a pluralized form # and try to find the singluar. elif term[-1] == 's' and klass_dict.has_key(term[ : -1]): ref = klass_dict[term[ : -1]] else: # The term is not in our dictionary. Emit a warning and use a # default ref. sys.stderr.write('Warning: encountered use of undefined term %s.\n' % term) ref = None # Add the ref attribute to the anchor element. if ref == None: href_text = '' else: href_text = ' href="%s"' % ref input = input[ : match.start()] \ + '%s' % (klass, href_text, term) \ + input[match.end() : ] # Write the result to standard output. print input # Write out the terms cache file. terms_file = open(terms_filename, 'w') pickle.dump(terms, terms_file) terms_file.close() ######################################################################## # Local Variables: # mode: python # indent-tabs-mode: nil # End: qmtest-2.4.1/NEWS0000664000076400007640000002065711122064222013070 0ustar stefanstefanNEWS ==== This file describes user-visible changes to QMTest. QMTest 2.4.1 ============ Address a couple of critical issues preventing QMTest from working with Python 2.6. QMTest 2.4 ========== A new "expectation_database" extension kind has been added, with two built-in implementations, previous_testrun.PreviousTestRun, and xml_expectation_database.XMLExpectationDatabase. The command-line interface has been enhanced to support this. A new CompilationTestDatabase has been added, and various related test classes and utility functions have been improved to support it. The QMTest documentation has been much improved. The tutorial has been restructured to contain three chapters: 1) concepts, 2) customization, 3) extension. Changes have been made to make QMTest work with Python 2.5. QMTest now installs its data into /share/qmtest, and its documentation into /share/doc/qmtest. QM 2.3 ====== There is now a "qmtest report" command-line option that can be used to create test reports from multiple result files. There is a new "host" extension kind (with a built-in set of predefined host types such as 'localhost.LocalHost', 'ssh_host.SSHHost', etc.) QMTest now installs its data into /share/qm, and its documentation into /share/doc/qm. QMTest has been made robust and more flexible. In particular, QMTest now runs with Python 2.4, and is now suitable for scripting as a programmatic way to access and manipulate result (and expectation) files, instead of the command line interface. QM 2.2 ====== Under Windows, tests derived from command.ExecTestBase that explicitly set environment variables for the child process did not operate correctly. This problem has been corrected. Resources are now destroyed in reverse order of creation. Signal masks are now set correctly for processes spawned by QMTest, even when QMTest is running with multiple threads. QMTest can provide output reports compatible with that from TET. QMTest's DejaGNU emulation has been updated and improved. QM 2.1.2 ======== A problem with the Windows packaging script that resulted in qmtest.py not being installed in the Python Scripts directory has been corrected. QM 2.1.1 ======== A problem that prevent ShellScriptTest from working on Windows with the native Windows command-interpreter has been fixed. QM 2.1 ====== QMTest requires Python 2.2 or greater. On Windows, we recommend that Mozilla be used with QMTest. Internet Explorer appears to handle incorrectly some forms that QMTest creates. CodeSourcery has validated the HTML using automated and manual methods, and believes that the problems lie with Internet Explorer and not with QMTest. There is now a "qmtest create" command-line option that can be used to create extension instances (such as tests, resources, or databases) programmatically. The "--class" option to the qmtest create-tdb" command now supports the same descriptor syntax as "qmtest create". There is a new "executable.TimeoutExecutable" class that can be used to run a child process with a timeout. The "command" test classes now make use of this functionality to support running child processes with a timeout. There is now a "-O" or "--outcomes" option for setting the expected outcomes, even when working within in the GUI. There is a new "--result-stream" option to "qmtest run" and "qmtest summarize" that allows users to specify custom result streams. The exit code returned by QMTest is now documented, and now distinguishes between a failure of QMTest to carry out the action requested by the user and the failure of a test run by QMTest. Comparisions between the expected standard output and actual standard output done by test classes in the "command" module now ignore line endings. This change facilitates moving tests between operating systems. A defect that could cause a multi-threaded or multi-process tests run to hang if a resource could not be set up has been corrected. A defect that resulted in resources being created only per run of the GUI, rather than once per test run, has been corrected. The XML results file format has been improved to make it more readable, and to make it easier to postprocess the XML. QMTest now correctly uses ";" as the separator in QMTEST_CLASS_PATH on Windows. A defect that could cause crashes in the RSHTarget class has been corrected. The QM_PYTHON environment variable is no longer honored by QMTest. To control which Python interpreter is used, run: /path/to/python /path/to/prefix/bin/qmtest explicitly. QM 2.0.3 ======== A JavaScript issue that prevented the pop-up menus in the GUI from working correctly with Mozilla 1.0.1 was corrected. A bug that could cause QMTest to hang when running tests in parallel has been corrected. QM 2.0.2 ======== When a test fails due to dependency on a resource that could not be set up, the GUI now displays a link to the resource result from the test result. (Previously, there was no way to get information about resource failures in the GUI.) The GUI now offers a choice of available prerequisite tests and resources when editing a test. The substitutions field for the FileContentsTest now works correctly in the GUI. This is an incompatible change; tests that use this test class will require hand-editing. An argument in a derived test or resource class which has the same name as an argument in a base class now overrides the base class argument. Therefore, every test class will have only one argument with a given name. (Previously, both the base and derived class arguments were present.) QM 2.0.1 ======== A bug that prevented the "New Resource" entry on the "File" menu from working has been fixed. QM 2.0 ====== Netscape 4 is no longer supported by the QMTest GUI. Mozilla 1.x and Internet Explorer 6 are the recommended browsers for use with the QMTest GUI. On UNIX-like systems, QMTest will now try to run "mozilla", rather than "netscape", by default. Tests are no longer run in a random order by default. To run tests in a random order, you must now use the "--random" option to "qmtest run". QMTest now has a "ProcessTarget" target class that can be used to run tests in parallel on systems that do not support threads. QMTest now requires that all extension classes be listed in the classes.qmc file in the directory that contains the extension class. QMTest now uses a uniform XML file format for all extension classes, including tests, resources, databases, and targets. This format will remain stable for the forseeable future. While QMTest 2.0 can read the formats created by previous versions of QMTest, it will only write files in the new format. Most users will be unaffected by these changes. New command-line options: ------------------------- QMTest now has a "--version" option. The "qmtest run" command now has a "--rerun" option to rerun only those tests which had unexpected outcomes when the tests were last run. The "qmtest run" command now has a "--random" option to run the tests in a random order. The "qmtest extensions" command can be used to list the available extension classes. The "qmtest register" command can be used to register new extension classes and to try loading an extension class. The "qmtest help" command is a synonym for "qmtest --help". The "qmtest run" and "qmtest gui" commands now use a file named "context" in the current directory as a context file if no explict -C option is provided. QM 1.1.5 ======== When loading a test, resource, or database class, the directory containing the extension class is placed at the front of the path used to search for modules. In previous versions of QMTest, it was placed at the back. QM 1.1.4 ======== The QMTest GUI no longer crashes when the "Cancel" button is hit when creating a new test suite. Commands like "qmtest create-tdb --attribute X=Y" where "Y" contains spaces are now handled correctly. QM 1.1.3 ======== The "-c" option to "qmtest run" did not work correctly in QM 1.1.2. This problem has been corrected. QM 1.1.2 ======== QM is now licensed under the GNU General Public License. The QMTest GUI has been substantially improved. It is now possible to load and save the context in the GUI. Numerous small bugs have been fixed. QM 1.1 ====== QMTest now works on systems that do not have support for threads, or, more precisely, when using a Python interpreter for which "import thread" fails. The Makefiles and build tree have been reorganized so as to make installation from source simpler. QMTest should now build on Debian GNU/Linux without configure options.