The related cleanup operation may get called after some of the imported Python
modules have already been unloaded (e.g. os.path), which may then cause the
shutil.rmtree() operation to fail in case the shutil module is imported on
demand. This has been seen when running the project's test suite using the
setup.py test command on Python 2.4.4.
Code wanting to support Python versions prior to 2.5 needs to re-raise
KeyboardInterrupt & SystemExit exceptions before handling the generic
'Exception' case, unless it really wants to gobble up those special
infrastructural exceptions. Python 2.5 made those exceptions parallel to the
Exception class and so no longer requires them to be handled specially by user
code.
Such exceptions need to be handled separately when catching the generic
Exception class under Python 2.4 or they get gobbled up by the generic exception
handling.
Now using setuptools 1.4.2 with Python 2.4 & 2.5, and using setuptools 3.3 with
later Python versions. This should help avoid installation issues in different
exotic use cases that were once not being handled by setuptools but have since
been corrected.
Now tested using:
* Python 2.4.3 x86
* Python 2.4.4 x86
* Python 2.7.6 x64
* Python 3.2.5 x64
* Python 3.3.3 x86
* Python 3.3.3 x64
* Python 3.3.5 x64
* Python 3.4.0 x86
* Python 3.4.0 x64
Minor stylistic run_all_tests.cmd script changes:
* Renamed several internal constants.
* Reordered tests to make those expected to fail more often run sooner.
This avoids issues with pytest xdist plugin collecting tests differently in
different test processes when running them using multiple parallal test
processes.
Kudos to Bruno Oliveira (nicoddemus at BitBucket) for researching related pytest
xdist usage problems, discovering & explaining the underlying issue as well as
providing an initial project patch for it.
Introduced a new 'Project implementation note #xxx' concept for documenting
unintuitive code without duplicating embedded explanation comments. Such
implementation notes now documented in the HACKING.rst project document.
Independent test parametrizations can be given using separate
@pytest.mark.parametrize test function decorators instead of having to write
extra code to package all their combinations into a single
@pytest.mark.parametrize decorator.
Many of the newly added unit tests marked as 'expected to fail' (xfail) since
the current suds implementation, inherited from the original suds library
project, does not support encoding CDATA XML data sections correctly.
Renamed internal needsEncoding() method to __needs_encoding().
Used double instead of single quotes in string literals.
Line wrapping at 79-columns.
Docstring & comment cleanup.
Updated how suds constructs its cached WSDL & XML identifiers to allow cached
data reuse between different processes with Python's hash randomization feature
enabled.
Previously constructed using the built-in Python hash() function, while now it
gets constructed using md5 hash.
Python's hash randomization (implemented since Python 2.6.8, enabled by default
since Python 3.3) was causing different processes to mangle their cached data
names differently.
Many thanks to Eugene Yakubovich for reporting the issue as well as providing
the initial fix & tests.
run_test_process() test utility function runs a given test script as an external
process and asserts that it returns a 0 exit code and output nothing to its
stdout or stderr output streams. Previously implemented as an internal worker in
the tests.test_cache test module and now extracted as a test utility function
sharable between different test modules.
Packaged related code in a new _assert_empty_cache_folder() test utility
function allowing asserting for both empty and non-empty cache folders.
Now reports more detailed related test failure messages.
Now correctly detect inaccessible test cache folders instead of silently
treating them as non-empty cache folders.
Extract into a separate tests.compare_sax test utility module.
Extract its unit tests into a separate tests.test_compare_sax unit test module.
Make sure the tests.compare_sax module content gets processed by pytest when
performing its asserting rewriting even if the module does not observe the usual
test module naming convention (i.e. it does not begin with 'test_').
Removed the no longer used tests.test_utility test utility module.
As a slight related cleanup, pytest configured so it no longer recognizes
Python modules with name suffix '_test.py' as test modules. Such names are not
used in this project so removing their lookup should speed up pytest's test
collection slightly.
** About running the new tests with disabled Python assertions **
Since the CompareSAX uses pytest assertions, it can not be tested when Python
assertions have been disabled in that module, but pytest assertion rewriting
saves us from this if it is enabled. This effectively means that the new tests
can not be run with disabled Python assertions without pytest's assertion
rewriting being enabled.
Since pytest assertion rewriting has not been implemented for Python versions
prior to 2.6, the new tests can not be run with disabled Python assertions using
such Python versions at all.
CompareSAX now reports in more detail where it detected a mismatch in its given
XML documents. The context information gets output to the process's standard
error stream.
In the future, it would be nice if we could somehow integrate this context
information inside standard pytest test failure reporting (both for assertion
failures & unhandled exceptions).
CompareSAX now treats empty string & None namespaces as matching. This has been
done because the following three XML elements all have the same namespace:
<a/>
<a xmlns=""/>
<ns:a xmlns:ns=""/>
however the suds SAX document model represents that namespace sometimes as an
empty string and sometimes as None.
Added embedded TODO comments to remove this equivalence both here and when
comparing an XML element's textual content as soon as the underlying suds SAX
document model gets updated to represent empty/missing text/namespaces
consistently.
Previous implementation simply reported that there is a mismatch, without
specifying exactly the type or the location of the mismatch. Now CompareSAX uses
assertions instead of return values to report back failed comparisons. Since the
code is localized to a pytest based test suite, this makes all such detected
mismatches be nicely reported by pytest, including a precise stack trace. The
stack trace can be used to locate the exact mismatch in the debugger.
CompareSAX.document2document() used to be artificially restricted to comparing
only SAX XML documents consisting of only a single child element. Now it knows
how to compare any two SAX XML documents, comparing its child elements the same
way an element's child elements are compared.
SAX XML document comparison test utility functions moved to the new module as
class methods under a new CompareSAX class:
compare_xml() --> CompareSAX.document2document()
compare_xml_element() --> CompareSAX.element2element()
compare_xml_string_to_string() --> CompareSAX.data2data()
compare_xml_to_string() --> CompareSAX.document2data()
Better documented the implemented SAX XML document comparison functionality.
Affected comparisons now assert their expected input data structure instead of
simply returning False in case differently structured input data is detected.
Extracted duplicate XML data SAX parsing code into a new private
CompareSAX.__parse_data() worker method.
Minor function code refactoring.
Always passing a tuple as a %-string formatting parameter.
Used double instead of single quotes in string literals.
Docstring & comment cleanup.
This is the exception message constructed when attempting to construct a
suds.sax.element.Element with a non-Element parent. It seems like someone forgot
to apply % string formatting in its construction.
Reordered module imports alphabetically.
Always passing a tuple as a %-string formatting parameter.
Used double instead of single quotes in string literals.
Docstring & comment cleanup.
All such block replaced with blocks catching Exception subclasses only so they
no longer eat up internal Python exceptions like SystemExit or
KeyboardInterrupt.
Extracted duplicate test data into named variables.
Renamed test data XML namespaces not used explicitly to avoid accidental
collisions with those used explicitly.
Shortened expected constructed SOAP request data.
Extracted duplicate test data into named variables.
Renamed internal Python names to not use the camelCase naming convention and
use underscores instead.
Updated tests using the shared WSDL schema construction to explicitly name the
included operation if they call it instead of relying on the operation being
called 'f' by default.
Always passing a tuple as a %-string formatting parameter.
Reimplemented named lambda's as regular local functions.