diff --git a/MANIFEST.in b/MANIFEST.in index a3c503e..bb9a846 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,5 @@ -include README.txt +include README.rst include CHANGES.txt recursive-include docs *.* -recursive-include src *.txt *.py *.tar.gz README +recursive-include wstools *.py diff --git a/README.mdown b/README.mdown deleted file mode 100644 index a89a559..0000000 --- a/README.mdown +++ /dev/null @@ -1,30 +0,0 @@ -[![Build Status](https://travis-ci.org/kartoch/wstools.svg?branch=master)](https://travis-ci.org/kartoch/wstools)[![Coverage Status](https://img.shields.io/coveralls/kartoch/wstools.svg)](https://coveralls.io/r/kartoch/wstools?branch=master) - -General -======== -- Homepage: https://github.com/pycontribs/wstools -- Mailing List: https://groups.google.com/forum/#!forum/pycontribs -- Package: http://pypi.python.org/pypi/wstools/ -- Docs (TBD): http://packages.python.org/wstools - -Credits -======== -Companies ---------- -|makinacom|_ - - * `Planet Makina Corpus `_ - * `Contact us `_ - -.. |makinacom| image:: http://depot.makina-corpus.org/public/logo.gif -.. _makinacom: http://www.makina-corpus.com - -Authors ------------- - -- Makina Corpus - -Contributors ------------------ -- Sorin Sbarnea - diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..fc60d50 --- /dev/null +++ b/README.rst @@ -0,0 +1,73 @@ +========================================================= +WSDL parsing services package for Web Services for Python +========================================================= + +. image:: https://pypip.in/py_versions/wstools/badge.svg?style=flat + :target: https://pypi.python.org/pypi/wstools/ + +.. image:: https://pypip.in/license/wstools/badge.svg?style=flat + :target: https://pypi.python.org/pypi/wstools/ + +.. image:: https://pypip.in/download/wstools/badge.svg?style=flat + :target: https://pypi.python.org/pypi/wstools/ + +.. image:: https://pypip.in/version/wstools/badge.svg?style=flat + :target: https://pypi.python.org/pypi/wstools/ + +.. image:: https://pypip.in/egg/wstools/badge.svg?style=flat + :target: https://pypi.python.org/pypi/wstools/ + +.. image:: https://pypip.in/wheel/wstools/badge.svg?style=flat + :target: https://pypi.python.org/pypi/wstools/ + +------------ + +.. image:: https://api.travis-ci.org/pycontribs/wstools.svg?branch=master + :target: https://travis-ci.org/pycontribs/wstools + +.. image:: https://pypip.in/status/wstools/badge.svg?style=flat + :target: https://pypi.python.org/pypi/wstools/ + +.. image:: https://img.shields.io/coveralls/pycontribs/wstools.svg + :target: https://coveralls.io/r/pycontribs/wstools + +.. image:: http://api.flattr.com/button/flattr-badge-large.png + :target: https://flattr.com/submit/auto?user_id=sbarnea&url=https://github.com/pycontribs/wstools&title=Python wstools&language=&tags=github&category=software + + +General +======= + +- Homepage: https://github.com/pycontribs/wstools +- Mailing List: https://groups.google.com/forum/#!forum/pycontribs +- Package: http://pypi.python.org/pypi/wstools/ +- Docs (TBD): http://packages.python.org/wstools + +Credits +======= + +Companies +--------- + +\|makinacom\|\_ + +- ``Planet Makina Corpus ``\ \_ +- ``Contact us ``\ \_ + +.. \|makinacom\| image:: http://depot.makina-corpus.org/public/logo.gif +.. \_makinacom: http://www.makina-corpus.com + +Authors +------- + +- Makina Corpus python@makina-corpus.com + +Contributors +------------ + +- Sorin Sbarnea sorin.sbarnea@gmail.com + +.. |Build Status| image:: https://travis-ci.org/kartoch/wstools.svg?branch=master + :target: https://travis-ci.org/kartoch/wstools +.. |Coverage Status| image:: https://img.shields.io/coveralls/kartoch/wstools.svg + :target: https://coveralls.io/r/kartoch/wstools?branch=master diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..87e0b3e --- /dev/null +++ b/setup.cfg @@ -0,0 +1,45 @@ +[metadata] +description-file = README + +[bdist_wheel] +universal = 1 + +[build_sphinx] +source-dir = docs +build-dir = docs/build +all_files = 1 + +[upload_sphinx] +upload-dir = docs/build/html + +[pytest] +norecursedirs = . .svn jira _build tmp* lib/third lib *.egg bin distutils build docs demo +python_files = *.py +addopts = -p no:xdist --ignore=setup.py --tb=long -rsxX -v --maxfail=10 --pep8 tests +# --maxfail=2 -n4 +# -n4 runs up to 4 parallel procs +# --maxfail=2 fail fast, dude +# --durations=3 report the top 3 longest tests + +# these are important for distributed testing, to speedup their execution we minimize what we sync +rsyncdirs = . jira demo docs +rsyncignore = .hg .git +pep8ignore = E501 E265 E127 E901 E128 E402 + +[pep8] +exclude=build,lib,.tox,third,*.egg,docs,packages +;filename= +;select +ignore=E501,E265,E402 +max-line-length=1024 +count=1 +;format +;quiet +;show-pep8 +;show-source +statistics=1 +;verbose=1 + +;PEP8_OPTS="--filename=*.py --exclude=lib --ignore=E501 scripts" +;pep8 $PEP8_OPTS --show-source --repeat +;pep8 --statistics -qq $PEP8_OPTS diff --git a/setup.py b/setup.py index 709a423..da10547 100644 --- a/setup.py +++ b/setup.py @@ -1,34 +1,171 @@ #!/usr/bin/env python - +import logging import os -from setuptools import setup +import re +import sys +import subprocess +import warnings +import codecs + +from setuptools import setup, find_packages, Command +from setuptools.command.test import test as TestCommand +NAME = "wstools" url = "https://github.com/pycontribs/wstools.git" +# Get the version - do not use normal import because it does break coverage +base_path = os.path.dirname(__file__) +fp = open(os.path.join(base_path, NAME, 'version.py')) +__version__ = re.compile(r".*__version__\s*=\s*['\"](.*?)['\"]", + re.S).match(fp.read()).group(1) +fp.close() + +# this should help getting annoying warnings from inside distutils +warnings.simplefilter('ignore', UserWarning) + + +class PyTest(TestCommand): + user_options = [('pytest-args=', 'a', "Arguments to pass to py.test")] + + def initialize_options(self): + TestCommand.initialize_options(self) + self.pytest_args = [] + + FORMAT = '%(levelname)-10s %(message)s' + logging.basicConfig(format=FORMAT) + logging.getLogger().setLevel(logging.INFO) + + # if we have pytest-cache module we enable the test failures first mode + try: + import pytest_cache + self.pytest_args.append("--ff") + except ImportError: + pass + self.pytest_args.append("-s") + + if sys.stdout.isatty(): + # when run manually we enable fail fast + self.pytest_args.append("--maxfail=1") + try: + import coveralls + self.pytest_args.append("--cov=%s" % NAME) + self.pytest_args.extend(["--cov-report", "term"]) + self.pytest_args.extend(["--cov-report", "xml"]) + + except ImportError: + pass -def read(*rnames): - return "\n" + open( - os.path.join('.', *rnames) - ).read() + def finalize_options(self): + TestCommand.finalize_options(self) + self.test_args = [] + self.test_suite = True -long_description = \ - "WSDL parsing services package for Web Services for Python. see" + url + def run_tests(self): + # before running tests we need to run autopep8 + try: + r = subprocess.check_call( + "python -m autopep8 -r --in-place wstools/ tests/", + shell=True) + except subprocess.CalledProcessError: + logging.getLogger().warn('autopep8 is not installed so ' + 'it will not be run') + # import here, cause outside the eggs aren't loaded + import pytest + errno = pytest.main(self.pytest_args) + sys.exit(errno) -from wstools.version import __version__ -install_requires = [ - 'docutils' -] +class Release(Command): + user_options = [] + + def initialize_options(self): + # Command.initialize_options(self) + pass + + def finalize_options(self): + # Command.finalize_options(self) + pass + + def run(self): + import json + try: + from urllib.request import urlopen + except ImportError: + from urllib2 import urlopen + response = urlopen( + "http://pypi.python.org/pypi/%s/json" % NAME) + data = json.load(codecs.getreader("utf-8")(response)) + released_version = data['info']['version'] + if released_version == __version__: + raise RuntimeError( + "This version was already released, remove it from PyPi if you want to release it again or increase the version number. http://pypi.python.org/pypi/%s/" % NAME) + elif released_version > __version__: + raise RuntimeError("Cannot release a version (%s) smaller than the PyPI current release (%s)." % ( + __version__, released_version)) + + +class PreRelease(Command): + user_options = [] + + def initialize_options(self): + # Command.initialize_options(self) + pass + + def finalize_options(self): + # Command.finalize_options(self) + pass + + def run(self): + import json + try: + from urllib.request import urlopen + except ImportError: + from urllib2 import urlopen + response = urlopen( + "http://pypi.python.org/pypi/%s/json" % NAME) + data = json.load(codecs.getreader("utf-8")(response)) + released_version = data['info']['version'] + if released_version >= __version__: + raise RuntimeError( + "Current version of the package is equal or lower than the already published ones (PyPi). Increse version to be able to pass prerelease stage.") + setup( - name="wstools", + name=NAME, version=__version__, - description="wstools", - maintainer="Gregory Warnes, kiorky, sorin", - maintainer_email="Gregory.R.Warnes@Pfizer.com, " - + " kiorky@cryptelium.net, " + "sorin.sbarnea+os@gmail.com", - url=url, - long_description=long_description, - packages=['wstools'], - install_requires=install_requires, + cmdclass={'test': PyTest, 'release': Release, 'prerelease': PreRelease}, + packages=find_packages(exclude=['tests']), + include_package_data=True, + install_requires=['docutils','six'], + + license='BSD', + description="WSDL parsing services package for Web Services for Python. see" + url, + long_description=open("README.rst").read(), + maintainer="Sorin Sbarnea", + maintainer_email="sorin.sbarnea@gmail.com", + author='Makina Corpus', + author_email='python@makina-corpus.com', + provides=[NAME], + url='https://github.com/pycontribs/wstools', + bugtrack_url='https://github.com/pycontribs/wstools/issues', + home_page='https://github.com/pycontribs/wstools', + keywords='api wstools wdsl web', + classifiers=[ + 'Programming Language :: Python', + 'Programming Language :: Python :: 2.5', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3', + 'Development Status :: 4 - Beta', + 'Environment :: Other Environment', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: BSD License', + 'Operating System :: OS Independent', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Topic :: Internet :: WWW/HTTP', + ], ) diff --git a/tests/config.txt b/tests/config.txt index 195c088..299acec 100644 --- a/tests/config.txt +++ b/tests/config.txt @@ -10,7 +10,7 @@ [services_by_file] ip2geo = data/ip2geo.wsdl zip2geo = data/zip2geo.wsdl -soapi-dlw = data/soapi-1.63.0-dlw.wsdl +soapi-dlw = data/soapi-1.63.0-dlw.wsdl soapi-re = data/soapi-1.63.0-re.wsdl ########################################################################## @@ -209,7 +209,7 @@ FOPService = http://live.capescience.com/wsdl/FOPService.wsdl FedRoutingDirectoryService = http://demo.soapam.com/services/FedEpayDirectory/FedEpayDirectoryService.wsdl GMChart = http://service.graphmagic.com/GMService/GraphMagic.asmx?wsdl GeoPlaces = http://www.codebump.com/services/placelookup.asmx?wsdl -GlobalWeather = http://live.capescience.com/wsdl/GlobalWeather.wsdl +GlobalWeatherComplex = http://live.capescience.com/wsdl/GlobalWeather.wsdl GoogleSearch = http://api.google.com/GoogleSearch.wsdl HPcatalogService = http://www.lixusnet.com/lixusnet/HPcatalog.jws?wsdl HTMLeMail = http://www.framewerks.com/WebServices/HTMLeMail/HTMLeMail.asmx?WSDL @@ -245,7 +245,7 @@ SendSMS = http://www.webservicex.net/SendSMS.asmx?WSDL Server = http://addison.ra.cwru.edu/orc/calendar_copy/server.php?wsdl Service = http://www.ejse.com/WeatherService/Service.asmx?WSDL SpamKillerService = http://wavendon.dsdata.co.uk/axis/services/SpamKiller?wsdl -StockQuotes = http://www.swanandmokashi.com/HomePage/WebServices/StockQuotes.asmx?WSDL +StockQuotesComplex = http://www.swanandmokashi.com/HomePage/WebServices/StockQuotes.asmx?WSDL TWSFissionDotNet = http://www.sidespace.com/ws/fission/fissiondotnet.php?wsdl TerraService = http://terraservice.net/TerraService.asmx?WSDL Transform = http://transform.dataconcert.com/transform.wsdl diff --git a/tests/test_wsdl.py b/tests/test_wsdl.py index cd1f8f0..6a1cfc7 100644 --- a/tests/test_wsdl.py +++ b/tests/test_wsdl.py @@ -7,11 +7,19 @@ import sys import unittest -import ConfigParser import os +import inspect +cmd_folder = os.path.abspath(os.path.join(os.path.split(inspect.getfile( + inspect.currentframe()))[0], "..")) +if cmd_folder not in sys.path: + sys.path.insert(0, cmd_folder) from wstools.Utility import DOM from wstools.WSDLTools import WSDLReader from wstools.TimeoutSocket import TimeoutError +try: + import configparser +except: + from six.moves import configparser cwd = 'tests' @@ -37,8 +45,11 @@ class WSDLToolsTestCase(unittest.TestCase): def setUp(self): makeTestSuite() - self.path = nameGenerator.next() - print self.path + if hasattr(nameGenerator, '__next__'): + self.path = nameGenerator.__next__() + else: + self.path = nameGenerator.next() + #print(self.path) sys.stdout.flush() def __str__(self): @@ -72,7 +83,7 @@ class WSDLToolsTestCase(unittest.TestCase): self.wsdl = WSDLReader().loadFromFile('tests/' + self.path) except TimeoutError: - print "connection timed out" + print("connection timed out") sys.stdout.flush() return except: @@ -104,8 +115,8 @@ class WSDLToolsTestCase(unittest.TestCase): raise try: - self.checkWSDLCollection('import', self.wsdl.imports, \ - key='namespace') + self.checkWSDLCollection('import', self.wsdl.imports, + key='namespace') except: self.path = self.path + ": wsdl.imports" raise @@ -131,9 +142,9 @@ class WSDLToolsTestCase(unittest.TestCase): raise if self.wsdl.extensions: - print 'No check for WSDLTools(%s) Extensions:' % (self.wsdl.name) + print('No check for WSDLTools(%s) Extensions:' % (self.wsdl.name)) for ext in self.wsdl.extensions: - print '\t', ext + print('\t', ext) def schemaAttributesDeclarations(self, schema, node): self.checkXSDCollection('attribute', schema.attr_decl, node) @@ -150,13 +161,14 @@ class WSDLToolsTestCase(unittest.TestCase): def setUpOptions(section): - cp = ConfigParser.ConfigParser() + cp = configparser.ConfigParser() + cp.optionxform = str cp.read(cwd + '/config.txt') if not cp.sections(): - print 'fatal error: configuration file config.txt not present' + print('fatal error: configuration file config.txt not present') sys.exit(0) if not cp.has_section(section): - print '%s section not present in configuration file, exiting' % section + print('%s section not present in configuration file, exiting' % section) sys.exit(0) return cp, len(cp.options(section)) diff --git a/tox.ini b/tox.ini index e69a7bd..672cd6c 100644 --- a/tox.ini +++ b/tox.ini @@ -1,6 +1,6 @@ [tox] minversion = 1.3 -envlist = py26,py27,py33,py34,flake8 +envlist = py26,py27,py34,flake8 [testenv] deps= diff --git a/wstools/.cvsignore b/wstools/.cvsignore deleted file mode 100644 index 0d20b64..0000000 --- a/wstools/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -*.pyc diff --git a/wstools/Namespaces.py b/wstools/Namespaces.py index 0e0e613..31c662f 100644 --- a/wstools/Namespaces.py +++ b/wstools/Namespaces.py @@ -136,6 +136,7 @@ WSRFLIST = (WSRF_V1_2,) class OASIS: + '''URLs for Oasis specifications ''' WSSE = "http://docs.oasis-open.org/wss/2004/01/" @@ -164,6 +165,7 @@ class OASIS: class APACHE: + ''' This name space is defined by AXIS and it is used for the TC in TCapache.py, Map and file attachment (DataHandler) @@ -222,6 +224,7 @@ WSA_LIST = (WSA200508, WSA200408, WSA200403, WSA200303) class _WSAW(str): + """ Define ADDRESS attribute to be compatible with WSA* layout """ diff --git a/wstools/TimeoutSocket.py b/wstools/TimeoutSocket.py index 4ec0f88..5b96716 100644 --- a/wstools/TimeoutSocket.py +++ b/wstools/TimeoutSocket.py @@ -51,7 +51,7 @@ class TimeoutSocket: apply(sock.connect, addr) sock.setblocking(timeout != 0) return 1 - except socket.error, why: + except socket.error as why: if not timeout: raise sock.setblocking(1) @@ -67,7 +67,7 @@ class TimeoutSocket: try: apply(sock.connect, addr) return 1 - except socket.error, why: + except socket.error as why: if len(why.args) == 1: code = 0 else: diff --git a/wstools/Utility.py b/wstools/Utility.py index 31becbc..eddb5aa 100644 --- a/wstools/Utility.py +++ b/wstools/Utility.py @@ -15,15 +15,27 @@ ident = "$Id$" +import copy import sys import types +import string +import six import socket import weakref from os.path import isfile -from string import join, strip, split -from UserDict import UserDict import urllib +try: + from urlparse import urljoin as basejoin +except: + from urllib.parse import urljoin as basejoin + +try: + from UserDict import UserDict + from UserDict import DictMixin +except ImportError: + from collections import UserDict + from collections import MutableMapping as DictMixin from .TimeoutSocket import TimeoutSocket, TimeoutError @@ -42,9 +54,10 @@ try: except ImportError: from http.client import HTTPConnection, HTTPSConnection - - -from exceptions import Exception +try: + from exceptions import Exception +except: + pass try: from ZSI import _get_idstr except: @@ -61,9 +74,10 @@ import xml.dom.minidom from xml.dom import Node import logging -from c14n import Canonicalize -from Namespaces import SCHEMA, SOAP, XMLNS, ZSI_SCHEMA_URI +from .c14n import Canonicalize +from .Namespaces import SCHEMA, SOAP, XMLNS, ZSI_SCHEMA_URI +DEFAULT = "".join try: from xml.dom.ext import SplitQName @@ -91,20 +105,6 @@ except: return return tuple(l) -# -# python2.3 urllib.basejoin does not remove current directory ./ -# from path and this causes problems on subsequent basejoins. -# -basejoin = urllib.basejoin -if sys.version_info[0:2] < (2, 4, 0, 'final', 0)[0:2]: - #basejoin = lambda base,url: urllib.basejoin(base,url.lstrip('./')) - token = './' - - def basejoin(base, url): - if url.startswith(token) is True: - return urllib.basejoin(base, url[2:]) - return urllib.basejoin(base, url) - class NamespaceError(Exception): @@ -235,7 +235,7 @@ def urlopen(url, timeout=20, redirects=None): if redirects is not None and location in redirects: raise RecursionError( 'Circular HTTP redirection detected.' - ) + ) if redirects is None: redirects = {} redirects[location] = 1 @@ -289,40 +289,40 @@ class DOM: return value raise ValueError( 'Unsupported SOAP envelope uri: %s' % uri - ) + ) def GetSOAPEnvUri(self, version): """Return the appropriate SOAP envelope uri for a given human-friendly SOAP version string (e.g. '1.1').""" - attrname = 'NS_SOAP_ENV_%s' % join(split(version, '.'), '_') + attrname = 'NS_SOAP_ENV_%s' % '_'.join(version.split('.')) value = getattr(self, attrname, None) if value is not None: return value raise ValueError( 'Unsupported SOAP version: %s' % version - ) + ) def GetSOAPEncUri(self, version): """Return the appropriate SOAP encoding uri for a given human-friendly SOAP version string (e.g. '1.1').""" - attrname = 'NS_SOAP_ENC_%s' % join(split(version, '.'), '_') + attrname = 'NS_SOAP_ENC_%s' % '_'.join(version.split('.')) value = getattr(self, attrname, None) if value is not None: return value raise ValueError( 'Unsupported SOAP version: %s' % version - ) + ) def GetSOAPActorNextUri(self, version): """Return the right special next-actor uri for a given human-friendly SOAP version string (e.g. '1.1').""" - attrname = 'SOAP_ACTOR_NEXT_%s' % join(split(version, '.'), '_') + attrname = 'SOAP_ACTOR_NEXT_%s' % '_'.join(version.split('.')) value = getattr(self, attrname, None) if value is not None: return value raise ValueError( 'Unsupported SOAP version: %s' % version - ) + ) # Namespace stuff related to XML Schema. NS_XSD_99 = 'http://www.w3.org/1999/XMLSchema' @@ -346,7 +346,7 @@ class DOM: NS_XSD_01: NS_XSI_01, } - for key, value in _xsd_uri_mapping.items(): + for key, value in copy.deepcopy(_xsd_uri_mapping).items(): _xsd_uri_mapping[value] = key def InstanceUriForSchemaUri(self, uri): @@ -391,52 +391,52 @@ class DOM: return value raise ValueError( 'Unsupported SOAP envelope uri: %s' % uri - ) + ) def GetWSDLUri(self, version): - attr = 'NS_WSDL_%s' % join(split(version, '.'), '_') + attr = 'NS_WSDL_%s' % '_'.join(version.split('.')) value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version - ) + ) def GetWSDLSoapBindingUri(self, version): - attr = 'NS_SOAP_BINDING_%s' % join(split(version, '.'), '_') + attr = 'NS_SOAP_BINDING_%s' % '_'.join(version.split('.')) value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version - ) + ) def GetWSDLHttpBindingUri(self, version): - attr = 'NS_HTTP_BINDING_%s' % join(split(version, '.'), '_') + attr = 'NS_HTTP_BINDING_%s' % '_'.join(version.split('.')) value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version - ) + ) def GetWSDLMimeBindingUri(self, version): - attr = 'NS_MIME_BINDING_%s' % join(split(version, '.'), '_') + attr = 'NS_MIME_BINDING_%s' % '_'.join(version.split('.')) value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version - ) + ) def GetWSDLHttpTransportUri(self, version): - attr = 'NS_SOAP_HTTP_%s' % join(split(version, '.'), '_') + attr = 'NS_SOAP_HTTP_%s' % '_'.join(version.split('.')) value = getattr(self, attr, None) if value is not None: return value raise ValueError( 'Unsupported WSDL version: %s' % version - ) + ) # Other xml namespace constants. NS_XMLNS = 'http://www.w3.org/2000/xmlns/' @@ -449,7 +449,7 @@ class DOM: return node.localName == name and \ (nsuri is None or self.nsUriMatch(node.namespaceURI, nsuri)) - def getElement(self, node, name, nsuri=None, default=join): + def getElement(self, node, name, nsuri=None, default=DEFAULT): """Return the first child of node with a matching name and namespace uri, or the default if one is provided.""" nsmatch = self.nsUriMatch @@ -457,13 +457,13 @@ class DOM: for child in node.childNodes: if child.nodeType == ELEMENT_NODE: if ((child.localName == name or name is None) and - (nsuri is None or nsmatch(child.namespaceURI, nsuri))): + (nsuri is None or nsmatch(child.namespaceURI, nsuri))): return child - if default is not join: + if default != DEFAULT: return default raise KeyError(name) - def getElementById(self, node, id, default=join): + def getElementById(self, node, id, default=DEFAULT): """Return the first child of node matching an id reference.""" attrget = self.getAttr ELEMENT_NODE = node.ELEMENT_NODE @@ -471,7 +471,7 @@ class DOM: if child.nodeType == ELEMENT_NODE: if attrget(child, 'id') == id: return child - if default is not join: + if default != DEFAULT: return default raise KeyError(name) @@ -503,7 +503,7 @@ class DOM: for child in node.childNodes: if child.nodeType == ELEMENT_NODE: if ((child.localName == name or name is None) and ( - (nsuri is None) or nsmatch(child.namespaceURI, nsuri))): + (nsuri is None) or nsmatch(child.namespaceURI, nsuri))): result.append(child) return result @@ -517,23 +517,35 @@ class DOM: return False return node.hasAttributeNS(nsuri, name) - def getAttr(self, node, name, nsuri=None, default=join): + def getAttr(self, node, name, nsuri=None, default=DEFAULT): """Return the value of the attribute named 'name' with the optional nsuri, or the default if one is specified. If nsuri is not specified, an attribute that matches the given name will be returned regardless of namespace.""" if nsuri is None: - result = node._attrs.get(name, None) + if node._attrs is None: + result = None + else: + result = node._attrs.get(name, None) if result is None: - for item in node._attrsNS.keys(): - if item[1] == name: - result = node._attrsNS[item] - break + if node._attrsNS is None: + result = None + else: + for item in node._attrsNS.keys(): + if item[1] == name: + result = node._attrsNS[item] + break else: - result = node._attrsNS.get((nsuri, name), None) + if node._attrsNS is None: + result = None + else: + if node._attrsNS is None: + result = None + else: + result = node._attrsNS.get((nsuri, name), None) if result is not None: return result.value - if default is not join: + if default != DEFAULT: return default return '' @@ -555,9 +567,9 @@ class DOM: if nodetype == child.TEXT_NODE or \ nodetype == child.CDATA_SECTION_NODE: result.append(child.nodeValue) - value = join(result, '') + value = ''.join(result) if preserve_ws is None: - value = strip(value) + value = value.strip() return value def findNamespaceURI(self, prefix, node): @@ -901,7 +913,7 @@ class ElementProxy(Base, MessageInterface): for attr in node.attributes.values(): if attr.namespaceURI == XMLNS.BASE \ and nsuri == attr.value: - return attr.localName + return attr.localName else: if node.parentNode: return self._getPrefix(node.parentNode, nsuri) @@ -1190,8 +1202,8 @@ class Collection(UserDict): self._func = key or self.default def __getitem__(self, key): - NumberTypes = (types.IntType, types.LongType, types.FloatType, - types.ComplexType) + NumberTypes = six.integer_types + NumberTypes = NumberTypes + (type(float), type(complex)) if isinstance(key, NumberTypes): return self.list[key] return self.data[key] @@ -1226,7 +1238,7 @@ class CollectionNS(UserDict): def __getitem__(self, key): self.targetNamespace = self.parent().targetNamespace - if isinstance(key, types.IntType): + if isinstance(key, six.integer_types): return self.list[key] elif self.__isSequence(key): nsuri, name = key @@ -1243,7 +1255,7 @@ class CollectionNS(UserDict): self.data[targetNamespace][key] = item def __isSequence(self, key): - return (type(key) in (types.TupleType, types.ListType) + return (isinstance(key, (tuple, list)) and len(key) == 2) def keys(self): diff --git a/wstools/WSDLTools.py b/wstools/WSDLTools.py index 4a8a4b2..d3e578c 100644 --- a/wstools/WSDLTools.py +++ b/wstools/WSDLTools.py @@ -21,6 +21,7 @@ from .XMLSchema import XMLSchema, SchemaReader, WSDLToolsAdapter class WSDLReader: + """A WSDLReader creates WSDL instances from urls and xml data.""" # Custom subclasses of WSDLReader may wish to implement a caching @@ -61,6 +62,7 @@ class WSDLReader: class WSDL: + """A WSDL object models a WSDL service description. WSDL objects may be created manually or loaded from an xml representation using a WSDLReader instance.""" @@ -90,7 +92,7 @@ class WSDL: if name in self.services: raise WSDLError( 'Duplicate service element: %s' % name - ) + ) item = Service(name, documentation) if targetNamespace: item.targetNamespace = targetNamespace @@ -101,7 +103,7 @@ class WSDL: if name in self.messages: raise WSDLError( 'Duplicate message element: %s.' % name - ) + ) item = Message(name, documentation) if targetNamespace: item.targetNamespace = targetNamespace @@ -112,7 +114,7 @@ class WSDL: if name in self.portTypes: raise WSDLError( 'Duplicate portType element: name' - ) + ) item = PortType(name, documentation) if targetNamespace: item.targetNamespace = targetNamespace @@ -123,7 +125,7 @@ class WSDL: if name in self.bindings: raise WSDLError( 'Duplicate binding element: %s' % name - ) + ) item = Binding(name, type, documentation) if targetNamespace: item.targetNamespace = targetNamespace @@ -182,7 +184,7 @@ class WSDL: if definitions is None: raise WSDLError( 'Missing element.' - ) + ) self.version = DOM.WSDLUriToVersion(definitions.namespaceURI) NS_WSDL = DOM.GetWSDLUri(self.version) @@ -261,7 +263,7 @@ class WSDL: if type is None: raise WSDLError( 'Missing type attribute for binding %s.' % name - ) + ) type = ParseQName(type, element) docs = GetDocumentation(element) binding = self.addBinding(name, type, docs, targetNamespace) @@ -318,7 +320,7 @@ class WSDL: if namespace is None or location is None: raise WSDLError( 'Invalid import element (missing namespace or location).' - ) + ) if base_location: location = basejoin(base_location, location) element.setAttributeNS(None, 'location', location) @@ -336,7 +338,7 @@ class WSDL: if imported is None: raise WSDLError( 'Import target element not found for: %s' % location - ) + ) imported_tns = DOM.findTargetNS(imported) if imported_tns != namespace: @@ -376,7 +378,9 @@ class WSDL: class Element: + """A class that provides common functions for WSDL element classes.""" + def __init__(self, name=None, documentation=''): self.name = name self.documentation = documentation @@ -402,6 +406,7 @@ class Element: class ImportElement(Element): + def __init__(self, namespace, location): self.namespace = namespace self.location = location @@ -438,6 +443,7 @@ class Types(Collection): class Message(Element): + def __init__(self, name, documentation=''): Element.__init__(self, name, documentation) self.parts = Collection(self) @@ -446,11 +452,11 @@ class Message(Element): if name in self.parts: raise WSDLError( 'Duplicate message part element: %s' % name - ) + ) if type is None and element is None: raise WSDLError( 'Missing type or element attribute for part: %s' % name - ) + ) item = MessagePart(name) item.element = element item.type = type @@ -467,7 +473,7 @@ class Message(Element): if typeref is None and elemref is None: raise WSDLError( 'No type or element attribute for part: %s' % name - ) + ) if typeref is not None: part.type = ParseTypeRef(typeref, element) if elemref is not None: @@ -508,6 +514,7 @@ class Message(Element): class MessagePart(Element): + def __init__(self, name): Element.__init__(self, name, '') self.element = None @@ -547,6 +554,7 @@ class MessagePart(Element): class PortType(Element): + '''PortType has a anyAttribute, thus must provide for an extensible mechanism for supporting such attributes. ResourceProperties is specified in WS-ResourceProperties. wsa:Action is specified in @@ -644,13 +652,14 @@ class PortType(Element): ns, name = self.resourceProperties prefix = epc.getPrefix(ns) epc.setAttributeNS(WSRF.PROPERTIES.LATEST, 'ResourceProperties', - '%s:%s' % (prefix, name)) + '%s:%s' % (prefix, name)) for op in self.operations: op.toDom(epc._getNode()) class Operation(Element): + def __init__(self, name, documentation='', parameterOrder=None): Element.__init__(self, name, documentation) self.parameterOrder = parameterOrder @@ -697,7 +706,7 @@ class Operation(Element): if name in self.faults: raise WSDLError( 'Duplicate fault element: %s' % name - ) + ) item = MessageRole('fault', message, name, documentation, action) self.faults[name] = item return item @@ -728,6 +737,7 @@ class Operation(Element): class MessageRole(Element): + def __init__(self, type, message, name='', documentation='', action=None): Element.__init__(self, name, documentation) self.message = message @@ -775,6 +785,7 @@ class MessageRole(Element): class Binding(Element): + def __init__(self, name, type, documentation=''): Element.__init__(self, name, documentation) self.operations = Collection(self) @@ -869,6 +880,7 @@ class Binding(Element): class OperationBinding(Element): + def __init__(self, name, documentation=''): Element.__init__(self, name, documentation) self.input = None @@ -952,6 +964,7 @@ class OperationBinding(Element): class MessageRoleBinding(Element): + def __init__(self, type, name='', documentation=''): Element.__init__(self, name, documentation) self.type = type @@ -976,7 +989,7 @@ class MessageRoleBinding(Element): if use is None: raise WSDLError( 'Invalid soap:body binding element.' - ) + ) ob = SoapBodyBinding(use, namespace, encstyle, parts) self.addExtension(ob) continue @@ -989,14 +1002,14 @@ class MessageRoleBinding(Element): if use is None or name is None: raise WSDLError( 'Invalid soap:fault binding element.' - ) + ) ob = SoapFaultBinding(name, use, namespace, encstyle) self.addExtension(ob) continue elif ns in DOM.NS_SOAP_BINDING_ALL and name in ( 'header', 'headerfault' - ): + ): encstyle = DOM.getAttr(e, 'encodingStyle', default=None) namespace = DOM.getAttr(e, 'namespace', default=None) message = DOM.getAttr(e, 'message') @@ -1055,6 +1068,7 @@ class MessageRoleBinding(Element): class Service(Element): + def __init__(self, name, documentation=''): Element.__init__(self, name, documentation) self.ports = Collection(self) @@ -1075,7 +1089,7 @@ class Service(Element): if name is None or binding is None: raise WSDLError( 'Invalid port element.' - ) + ) binding = ParseQName(binding, element) port = self.addPort(name, binding, docs) port.load_ex(GetExtensions(element)) @@ -1096,6 +1110,7 @@ class Service(Element): class Port(Element): + def __init__(self, name, binding, documentation=''): Element.__init__(self, name, documentation) self.binding = binding @@ -1127,7 +1142,7 @@ class Port(Element): return item raise WSDLError( 'No address binding found in port.' - ) + ) def load_ex(self, elements): for e in elements: @@ -1161,6 +1176,7 @@ class Port(Element): class SoapBinding: + def __init__(self, transport, style='rpc'): self.transport = transport self.style = style @@ -1179,6 +1195,7 @@ class SoapBinding: class SoapAddressBinding: + def __init__(self, location): self.location = location @@ -1193,6 +1210,7 @@ class SoapAddressBinding: class SoapOperationBinding: + def __init__(self, soapAction=None, style=None): self.soapAction = soapAction self.style = style @@ -1211,11 +1229,12 @@ class SoapOperationBinding: class SoapBodyBinding: + def __init__(self, use, namespace=None, encodingStyle=None, parts=None): if not use in ('literal', 'encoded'): raise WSDLError( 'Invalid use attribute value: %s' % use - ) + ) self.encodingStyle = encodingStyle self.namespace = namespace if type(parts) in (type(''), type(u'')): @@ -1235,11 +1254,12 @@ class SoapBodyBinding: class SoapFaultBinding: + def __init__(self, name, use, namespace=None, encodingStyle=None): if not use in ('literal', 'encoded'): raise WSDLError( 'Invalid use attribute value: %s' % use - ) + ) self.encodingStyle = encodingStyle self.namespace = namespace self.name = name @@ -1261,11 +1281,12 @@ class SoapFaultBinding: class SoapHeaderBinding: + def __init__(self, message, part, use, namespace=None, encodingStyle=None): if not use in ('literal', 'encoded'): raise WSDLError( 'Invalid use attribute value: %s' % use - ) + ) self.encodingStyle = encodingStyle self.namespace = namespace self.message = message @@ -1280,16 +1301,19 @@ class SoapHeaderFaultBinding(SoapHeaderBinding): class HttpBinding: + def __init__(self, verb): self.verb = verb class HttpAddressBinding: + def __init__(self, location): self.location = location class HttpOperationBinding: + def __init__(self, location): self.location = location @@ -1303,17 +1327,20 @@ class HttpUrlEncodedBinding: class MimeContentBinding: + def __init__(self, part=None, type=None): self.part = part self.type = type class MimeXmlBinding: + def __init__(self, part=None): self.part = part class MimeMultipartRelatedBinding: + def __init__(self): self.parts = [] @@ -1326,6 +1353,7 @@ class MimeMultipartRelatedBinding: class MimePartBinding: + def __init__(self): self.items = [] @@ -1353,7 +1381,7 @@ class MimePartBinding: if use is None: raise WSDLError( 'Invalid soap:body binding element.' - ) + ) ob = SoapBodyBinding(use, namespace, encstyle, parts) self.items.append(ob) continue @@ -1397,7 +1425,7 @@ def GetDocumentation(element): def GetExtensions(element): return [item for item in DOM.getElements(element, None, None) - if item.namespaceURI != DOM.NS_WSDL] + if item.namespaceURI != DOM.NS_WSDL] def GetWSAActionFault(operation, name): @@ -1446,8 +1474,8 @@ def FindExtensions(object, kind, t_type=type(())): result = [] namespaceURI, name = kind return [item for item in object.extensions - if hasattr(item, 'nodeType') \ - and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \ + if hasattr(item, 'nodeType') + and DOM.nsUriMatch(namespaceURI, item.namespaceURI) and item.name == name] return [item for item in object.extensions if isinstance(item, kind)] @@ -1457,8 +1485,8 @@ def FindExtension(object, kind, t_type=type(())): namespaceURI, name = kind for item in object.extensions: if hasattr(item, 'nodeType') \ - and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \ - and item.name == name: + and DOM.nsUriMatch(namespaceURI, item.namespaceURI) \ + and item.name == name: return item else: for item in object.extensions: @@ -1468,6 +1496,7 @@ def FindExtension(object, kind, t_type=type(())): class SOAPCallInfo: + """SOAPCallInfo captures the important binding information about a SOAP operation, in a structure that is easier to work with than raw WSDL structures.""" @@ -1547,7 +1576,9 @@ class SOAPCallInfo: class ParameterInfo: + """A ParameterInfo object captures parameter binding information.""" + def __init__(self, name, type, namespace=None, element_type=0): if element_type: self.element_type = 1 @@ -1562,7 +1593,9 @@ class ParameterInfo: class HeaderInfo(ParameterInfo): + """A HeaderInfo object captures SOAP header binding information.""" + def __init__(self, name, type, namespace, element_type=None): ParameterInfo.__init__(self, name, type, namespace, element_type) @@ -1614,7 +1647,7 @@ def callInfoFromWSDL(port, name): part.element or part.type, item.namespace, element_type=part.element and 1 or 0 - ) + ) header.encodingStyle = item.encodingStyle body = msgrole.findBinding(SoapBodyBinding) @@ -1636,7 +1669,7 @@ def callInfoFromWSDL(port, name): part.name, part.element or part.type, element_type=part.element and 1 or 0 - ) + ) if operation.output is not None: try: @@ -1665,7 +1698,7 @@ def callInfoFromWSDL(port, name): part.element or part.type, item.namespace, element_type=part.element and 1 or 0 - ) + ) header.encodingStyle = item.encodingStyle body = msgrole.findBinding(SoapBodyBinding) @@ -1688,6 +1721,6 @@ def callInfoFromWSDL(port, name): part.name, part.element or part.type, element_type=part.element and 1 or 0 - ) + ) return callinfo diff --git a/wstools/XMLSchema.py b/wstools/XMLSchema.py index bd4f39f..2cdb926 100644 --- a/wstools/XMLSchema.py +++ b/wstools/XMLSchema.py @@ -20,15 +20,20 @@ import weakref import sys import warnings import logging -from Namespaces import SCHEMA, XMLNS, SOAP, APACHE -from Utility import DOM, DOMException, Collection, SplitQName, basejoin -from StringIO import StringIO +from .Namespaces import SCHEMA, XMLNS, SOAP, APACHE +from .Utility import DOM, DOMException, Collection, SplitQName, basejoin +try: + from StringIO import StringIO +except: + # from io import StringIO + from io import BytesIO as StringIO # If we have no threading, this should be a no-op try: from threading import RLock except ImportError: class RLock: + def acquire(): pass @@ -56,6 +61,7 @@ def GetSchema(component): class SchemaReader: + """A SchemaReader creates XMLSchema objects from urls and xml data. """ @@ -175,6 +181,7 @@ class NoSchemaLocationWarning(Exception): # DOM Utility Adapters ########################## class DOMAdapterInterface: + def hasattr(self, attr, ns=None): """return true if node has attribute attr -- attribute to check for @@ -227,8 +234,10 @@ class DOMAdapterInterface: class DOMAdapter(DOMAdapterInterface): + """Adapter for ZSI.Utility.DOM """ + def __init__(self, node=None): """Reset all instance variables. element -- DOM document, node, or None @@ -263,8 +272,9 @@ class DOMAdapter(DOMAdapterInterface): def setAttributeDictionary(self): self.__attributes = {} - for v in self.__node._attrs.values(): - self.__attributes[v.nodeName] = v.nodeValue + if self.__node._attrs: + for v in self.__node._attrs.values(): + self.__attributes[v.nodeName] = v.nodeValue def getAttributeDictionary(self): if not self.__attributes: @@ -307,6 +317,7 @@ class DOMAdapter(DOMAdapterInterface): class XMLBase: + """ These class variables are for string indentation. """ tag = None @@ -331,116 +342,135 @@ class XMLBase: class DefinitionMarker: + """marker for definitions """ pass class DeclarationMarker: + """marker for declarations """ pass class AttributeMarker: + """marker for attributes """ pass class AttributeGroupMarker: + """marker for attribute groups """ pass class WildCardMarker: + """marker for wildcards """ pass class ElementMarker: + """marker for wildcards """ pass class ReferenceMarker: + """marker for references """ pass class ModelGroupMarker: + """marker for model groups """ pass class AllMarker(ModelGroupMarker): + """marker for all model group """ pass class ChoiceMarker(ModelGroupMarker): + """marker for choice model group """ pass class SequenceMarker(ModelGroupMarker): + """marker for sequence model group """ pass class ExtensionMarker: + """marker for extensions """ pass class RestrictionMarker: + """marker for restrictions """ - facets = ['enumeration', 'length', 'maxExclusive', 'maxInclusive',\ - 'maxLength', 'minExclusive', 'minInclusive', 'minLength',\ - 'pattern', 'fractionDigits', 'totalDigits', 'whiteSpace'] + facets = ['enumeration', 'length', 'maxExclusive', 'maxInclusive', + 'maxLength', 'minExclusive', 'minInclusive', 'minLength', + 'pattern', 'fractionDigits', 'totalDigits', 'whiteSpace'] class SimpleMarker: + """marker for simple type information """ pass class ListMarker: + """marker for simple type list """ pass class UnionMarker: + """marker for simple type Union """ pass class ComplexMarker: + """marker for complex type information """ pass class LocalMarker: + """marker for complex type information """ pass class MarkerInterface: + def isDefinition(self): return isinstance(self, DefinitionMarker) @@ -500,6 +530,7 @@ class MarkerInterface: # Schema Components ######################################################### class XMLSchemaComponent(XMLBase, MarkerInterface): + """ class variables: required -- list of required attributes @@ -529,9 +560,9 @@ class XMLSchemaComponent(XMLBase, MarkerInterface): self._parent = weakref.ref(parent) if not self.__class__ == XMLSchemaComponent\ - and not (type(self.__class__.required) == type(XMLSchemaComponent.required)\ - and type(self.__class__.attributes) == type(XMLSchemaComponent.attributes)\ - and type(self.__class__.contents) == type(XMLSchemaComponent.contents)): + and not (type(self.__class__.required) == type(XMLSchemaComponent.required) + and type(self.__class__.attributes) == type(XMLSchemaComponent.attributes) + and type(self.__class__.contents) == type(XMLSchemaComponent.contents)): raise RuntimeError('Bad type for a class variable in %s' % self.__class__) def getItemTrace(self): @@ -673,12 +704,12 @@ class XMLSchemaComponent(XMLBase, MarkerInterface): if prefix == XMLSchemaComponent.xml: return XMLNS.XML parent = self - ns = self.attributes[XMLSchemaComponent.xmlns].get(prefix or\ - XMLSchemaComponent.xmlns_key) + ns = self.attributes[XMLSchemaComponent.xmlns].get(prefix or + XMLSchemaComponent.xmlns_key) while not ns: parent = parent._parent() - ns = parent.attributes[XMLSchemaComponent.xmlns].get(prefix or\ - XMLSchemaComponent.xmlns_key) + ns = parent.attributes[XMLSchemaComponent.xmlns].get(prefix or + XMLSchemaComponent.xmlns_key) if not ns and isinstance(parent, WSDLToolsAdapter): if prefix is None: return '' @@ -768,8 +799,8 @@ class XMLSchemaComponent(XMLBase, MarkerInterface): self.attributes[k] = [] for qname in qnames.split(): prefix, value = SplitQName(qname) - self.attributes['memberTypes'].append(\ - TypeDescriptionComponent(\ + self.attributes['memberTypes'].append( + TypeDescriptionComponent( (self.getXMLNS(prefix), value))) def getContents(self, node): @@ -808,11 +839,12 @@ class XMLSchemaComponent(XMLBase, MarkerInterface): continue if (a not in self.__class__.attributes.keys()) and not\ - (self.isAttribute() and self.isReference()): + (self.isAttribute() and self.isReference()): raise SchemaError('%s, unknown attribute(%s, %s)' % (self.getItemTrace(), a, self.attributes[a])) class WSDLToolsAdapter(XMLSchemaComponent): + """WSDL Adapter to grab the attributes from the wsdl document node. """ attributes = {'name': None, 'targetNamespace': None} @@ -829,6 +861,7 @@ class WSDLToolsAdapter(XMLSchemaComponent): class Notation(XMLSchemaComponent): + """ parent: schema @@ -863,6 +896,7 @@ class Notation(XMLSchemaComponent): class Annotation(XMLSchemaComponent): + """ parent: all,any,anyAttribute,attribute,attributeGroup,choice,complexContent, @@ -900,6 +934,7 @@ class Annotation(XMLSchemaComponent): self.content = tuple(content) class Documentation(XMLSchemaComponent): + """ parent: annotation @@ -935,6 +970,7 @@ class Annotation(XMLSchemaComponent): self.content = tuple(content) class Appinfo(XMLSchemaComponent): + """ parent: annotation @@ -971,12 +1007,14 @@ class Annotation(XMLSchemaComponent): class XMLSchemaFake: # This is temporary, for the benefit of WSDL until the real thing works. + def __init__(self, element): self.targetNamespace = DOM.getAttr(element, 'targetNamespace') self.element = element class XMLSchema(XMLSchemaComponent): + """A schema is a collection of schema components derived from one or more schema documents, that is, one or more element information items. It represents the abstract notion of a schema @@ -1015,17 +1053,17 @@ class XMLSchema(XMLSchemaComponent): notations -- global notations """ attributes = {'id': None, - 'version': None, - 'xml: lang': None, - 'targetNamespace': None, - 'attributeFormDefault': 'unqualified', - 'elementFormDefault': 'unqualified', - 'blockDefault': None, - 'finalDefault': None} + 'version': None, + 'xml: lang': None, + 'targetNamespace': None, + 'attributeFormDefault': 'unqualified', + 'elementFormDefault': 'unqualified', + 'blockDefault': None, + 'finalDefault': None} contents = {'xsd': ('include', 'import', 'redefine', 'annotation', - 'attribute', 'attributeGroup', 'complexType', - 'element', 'group', 'notation', 'simpleType', - 'annotation')} + 'attribute', 'attributeGroup', 'complexType', + 'element', 'group', 'notation', 'simpleType', + 'annotation')} empty_namespace = '' tag = 'schema' @@ -1096,7 +1134,7 @@ class XMLSchema(XMLSchemaComponent): if not isinstance(schema, XMLSchema): raise TypeError('expecting a Schema instance') if not schema.targetNamespace or\ - schema.targetNamespace == self.targetNamespace: + schema.targetNamespace == self.targetNamespace: self._included_schemas[schemaLocation] = schema else: raise SchemaError('include schema bad targetNamespace') @@ -1243,6 +1281,7 @@ class XMLSchema(XMLSchemaComponent): del slocd[import_ns] class _LazyEvalImport(str): + '''Lazy evaluation of import, replace entry in self.imports.''' #attributes = dict(namespace=import_ns) def getSchema(namespace): @@ -1265,8 +1304,8 @@ class XMLSchema(XMLSchemaComponent): tp._schema = schema if import_ns in self.getImportSchemas(): - warnings.warn(\ - 'Detected multiple imports of the namespace "%s" '\ + warnings.warn( + 'Detected multiple imports of the namespace "%s" ' % import_ns) self.addImportSchema(schema) @@ -1310,6 +1349,7 @@ class XMLSchema(XMLSchemaComponent): break class Import(XMLSchemaComponent): + """ parent: schema @@ -1383,6 +1423,7 @@ class XMLSchema(XMLSchemaComponent): reader.loadFromURL(self.attributes.get('schemaLocation'), schema) class Include(XMLSchemaComponent): + """ parent: schema @@ -1394,7 +1435,7 @@ class XMLSchema(XMLSchemaComponent): """ required = ['schemaLocation'] attributes = {'id': None, - 'schemaLocation': None} + 'schemaLocation': None} contents = {'xsd': ['annotation']} tag = 'include' @@ -1437,9 +1478,10 @@ class XMLSchema(XMLSchemaComponent): return self._schema -class AttributeDeclaration(XMLSchemaComponent,\ - AttributeMarker,\ +class AttributeDeclaration(XMLSchemaComponent, + AttributeMarker, DeclarationMarker): + """ parent: schema @@ -1454,10 +1496,10 @@ class AttributeDeclaration(XMLSchemaComponent,\ """ required = ['name'] attributes = {'id': None, - 'name': None, - 'type': None, - 'default': None, - 'fixed': None} + 'name': None, + 'type': None, + 'default': None, + 'fixed': None} contents = {'xsd': ['annotation', 'simpleType']} tag = 'attribute' @@ -1484,10 +1526,11 @@ class AttributeDeclaration(XMLSchemaComponent,\ raise SchemaError('Unknown component (%s)' % (i.getTagName())) -class LocalAttributeDeclaration(AttributeDeclaration,\ - AttributeMarker,\ - LocalMarker,\ +class LocalAttributeDeclaration(AttributeDeclaration, + AttributeMarker, + LocalMarker, DeclarationMarker): + """ parent: complexType, restriction, extension, attributeGroup @@ -1504,12 +1547,12 @@ class LocalAttributeDeclaration(AttributeDeclaration,\ """ required = ['name'] attributes = {'id': None, - 'name': None, - 'type': None, - 'form': lambda self: GetSchema(self).getAttributeFormDefault(), - 'use': 'optional', - 'default': None, - 'fixed': None} + 'name': None, + 'type': None, + 'form': lambda self: GetSchema(self).getAttributeFormDefault(), + 'use': 'optional', + 'default': None, + 'fixed': None} contents = {'xsd': ['annotation', 'simpleType']} def __init__(self, parent): @@ -1533,10 +1576,11 @@ class LocalAttributeDeclaration(AttributeDeclaration,\ raise SchemaError('Unknown component (%s)' % (i.getTagName())) -class AttributeWildCard(XMLSchemaComponent,\ - AttributeMarker,\ - DeclarationMarker,\ +class AttributeWildCard(XMLSchemaComponent, + AttributeMarker, + DeclarationMarker, WildCardMarker): + """ parents: complexType, restriction, extension, attributeGroup @@ -1549,8 +1593,8 @@ class AttributeWildCard(XMLSchemaComponent,\ annotation? """ attributes = {'id': None, - 'namespace': '##any', - 'processContents': 'strict'} + 'namespace': '##any', + 'processContents': 'strict'} contents = {'xsd': ['annotation']} tag = 'anyAttribute' @@ -1571,9 +1615,10 @@ class AttributeWildCard(XMLSchemaComponent,\ raise SchemaError('Unknown component (%s)' % (i.getTagName())) -class AttributeReference(XMLSchemaComponent,\ - AttributeMarker,\ +class AttributeReference(XMLSchemaComponent, + AttributeMarker, ReferenceMarker): + """ parents: complexType, restriction, extension, attributeGroup @@ -1588,10 +1633,10 @@ class AttributeReference(XMLSchemaComponent,\ """ required = ['ref'] attributes = {'id': None, - 'ref': None, - 'use': 'optional', - 'default': None, - 'fixed': None} + 'ref': None, + 'use': 'optional', + 'default': None, + 'fixed': None} contents = {'xsd': ['annotation']} tag = 'attribute' @@ -1615,9 +1660,10 @@ class AttributeReference(XMLSchemaComponent,\ raise SchemaError('Unknown component (%s)' % (i.getTagName())) -class AttributeGroupDefinition(XMLSchemaComponent,\ - AttributeGroupMarker,\ +class AttributeGroupDefinition(XMLSchemaComponent, + AttributeGroupMarker, DefinitionMarker): + """ parents: schema, redefine @@ -1629,7 +1675,7 @@ class AttributeGroupDefinition(XMLSchemaComponent,\ """ required = ['name'] attributes = {'id': None, - 'name': None} + 'name': None} contents = {'xsd': ['annotation', 'attribute', 'attributeGroup', 'anyAttribute']} tag = 'attributeGroup' @@ -1673,9 +1719,10 @@ class AttributeGroupDefinition(XMLSchemaComponent,\ self.attr_content = tuple(content) -class AttributeGroupReference(XMLSchemaComponent,\ - AttributeGroupMarker,\ +class AttributeGroupReference(XMLSchemaComponent, + AttributeGroupMarker, ReferenceMarker): + """ parents: complexType, restriction, extension, attributeGroup @@ -1687,7 +1734,7 @@ class AttributeGroupReference(XMLSchemaComponent,\ """ required = ['ref'] attributes = {'id': None, - 'ref': None} + 'ref': None} contents = {'xsd': ['annotation']} tag = 'attributeGroup' @@ -1718,6 +1765,7 @@ class AttributeGroupReference(XMLSchemaComponent,\ # Elements ##################################################### class IdentityConstrants(XMLSchemaComponent): + """Allow one to uniquely identify nodes in a document and ensure the integrity of references between them. @@ -1725,6 +1773,7 @@ class IdentityConstrants(XMLSchemaComponent): selector -- XPath to selected nodes fields -- list of XPath to key field """ + def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.selector = None @@ -1757,6 +1806,7 @@ class IdentityConstrants(XMLSchemaComponent): self.fields = tuple(fields) class Constraint(XMLSchemaComponent): + def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None @@ -1777,6 +1827,7 @@ class IdentityConstrants(XMLSchemaComponent): raise SchemaError('Unknown component (%s)' % (i.getTagName())) class Selector(Constraint): + """ parent: unique, key, keyref @@ -1788,11 +1839,12 @@ class IdentityConstrants(XMLSchemaComponent): """ required = ['xpath'] attributes = {'id': None, - 'xpath': None} + 'xpath': None} contents = {'xsd': ['annotation']} tag = 'selector' class Field(Constraint): + """ parent: unique, key, keyref @@ -1804,12 +1856,13 @@ class IdentityConstrants(XMLSchemaComponent): """ required = ['xpath'] attributes = {'id': None, - 'xpath': None} + 'xpath': None} contents = {'xsd': ['annotation']} tag = 'field' class Unique(IdentityConstrants): + """ Enforce fields are unique w/i a specified scope. parent: @@ -1822,12 +1875,13 @@ class Unique(IdentityConstrants): """ required = ['name'] attributes = {'id': None, - 'name': None} + 'name': None} contents = {'xsd': ['annotation', 'selector', 'field']} tag = 'unique' class Key(IdentityConstrants): + """ Enforce fields are unique w/i a specified scope, and all field values are present w/i document. Fields cannot be nillable. @@ -1842,12 +1896,13 @@ class Key(IdentityConstrants): """ required = ['name'] attributes = {'id': None, - 'name': None} + 'name': None} contents = {'xsd': ['annotation', 'selector', 'field']} tag = 'key' class KeyRef(IdentityConstrants): + """ Ensure a match between two sets of values in an instance. parent: @@ -1861,15 +1916,16 @@ class KeyRef(IdentityConstrants): """ required = ['name', 'refer'] attributes = {'id': None, - 'name': None, - 'refer': None} + 'name': None, + 'refer': None} contents = {'xsd': ['annotation', 'selector', 'field']} tag = 'keyref' -class ElementDeclaration(XMLSchemaComponent,\ - ElementMarker,\ +class ElementDeclaration(XMLSchemaComponent, + ElementMarker, DeclarationMarker): + """ parents: schema @@ -1892,17 +1948,17 @@ class ElementDeclaration(XMLSchemaComponent,\ """ required = ['name'] attributes = {'id': None, - 'name': None, - 'type': None, - 'default': None, - 'fixed': None, - 'nillable': 0, - 'abstract': 0, - 'substitutionGroup': None, - 'block': lambda self: self._parent().getBlockDefault(), - 'final': lambda self: self._parent().getFinalDefault()} - contents = {'xsd': ['annotation', 'simpleType', 'complexType', 'key',\ - 'keyref', 'unique']} + 'name': None, + 'type': None, + 'default': None, + 'fixed': None, + 'nillable': 0, + 'abstract': 0, + 'substitutionGroup': None, + 'block': lambda self: self._parent().getBlockDefault(), + 'final': lambda self: self._parent().getFinalDefault()} + contents = {'xsd': ['annotation', 'simpleType', 'complexType', 'key', + 'keyref', 'unique']} tag = 'element' def __init__(self, parent): @@ -1937,7 +1993,7 @@ class ElementDeclaration(XMLSchemaComponent,\ return TypeDescriptionComponent((v, 'anyType')) if isinstance(parent, WSDLToolsAdapter)\ - or not hasattr(parent, '_parent'): + or not hasattr(parent, '_parent'): break parent = parent._parent() @@ -2000,8 +2056,9 @@ class ElementDeclaration(XMLSchemaComponent,\ self.constraints = constraints -class LocalElementDeclaration(ElementDeclaration,\ +class LocalElementDeclaration(ElementDeclaration, LocalMarker): + """ parents: all, choice, sequence @@ -2021,18 +2078,18 @@ class LocalElementDeclaration(ElementDeclaration,\ """ required = ['name'] attributes = {'id': None, - 'name': None, - 'form': lambda self: GetSchema(self).getElementFormDefault(), - 'type': None, - 'minOccurs': '1', - 'maxOccurs': '1', - 'default': None, - 'fixed': None, - 'nillable': 0, - 'abstract': 0, - 'block': lambda self: GetSchema(self).getBlockDefault()} - contents = {'xsd': ['annotation', 'simpleType', 'complexType', 'key',\ - 'keyref', 'unique']} + 'name': None, + 'form': lambda self: GetSchema(self).getElementFormDefault(), + 'type': None, + 'minOccurs': '1', + 'maxOccurs': '1', + 'default': None, + 'fixed': None, + 'nillable': 0, + 'abstract': 0, + 'block': lambda self: GetSchema(self).getBlockDefault()} + contents = {'xsd': ['annotation', 'simpleType', 'complexType', 'key', + 'keyref', 'unique']} def isQualified(self): """ @@ -2048,9 +2105,10 @@ Local elements can be qualified or unqualifed according raise SchemaError('Bad form (%s) for element: %s' % (form, self.getItemTrace())) -class ElementReference(XMLSchemaComponent,\ - ElementMarker,\ +class ElementReference(XMLSchemaComponent, + ElementMarker, ReferenceMarker): + """ parents: all, choice, sequence @@ -2064,9 +2122,9 @@ class ElementReference(XMLSchemaComponent,\ """ required = ['ref'] attributes = {'id': None, - 'ref': None, - 'minOccurs': '1', - 'maxOccurs': '1'} + 'ref': None, + 'minOccurs': '1', + 'maxOccurs': '1'} contents = {'xsd': ['annotation']} tag = 'element' @@ -2097,6 +2155,7 @@ class ElementReference(XMLSchemaComponent,\ class ElementWildCard(LocalElementDeclaration, WildCardMarker): + """ parents: choice, sequence @@ -2112,10 +2171,10 @@ class ElementWildCard(LocalElementDeclaration, WildCardMarker): """ required = [] attributes = {'id': None, - 'minOccurs': '1', - 'maxOccurs': '1', - 'namespace': '##any', - 'processContents': 'strict'} + 'minOccurs': '1', + 'maxOccurs': '1', + 'namespace': '##any', + 'processContents': 'strict'} contents = {'xsd': ['annotation']} tag = 'any' @@ -2154,8 +2213,9 @@ class ElementWildCard(LocalElementDeclaration, WildCardMarker): ###################################################### # Model Groups ##################################################### -class Sequence(XMLSchemaComponent,\ +class Sequence(XMLSchemaComponent, SequenceMarker): + """ parents: complexType, extension, restriction, group, choice, sequence @@ -2168,10 +2228,10 @@ class Sequence(XMLSchemaComponent,\ annotation?, (element | group | choice | sequence | any)* """ attributes = {'id': None, - 'minOccurs': '1', - 'maxOccurs': '1'} - contents = {'xsd': ['annotation', 'element', 'group', 'choice', 'sequence',\ - 'any']} + 'minOccurs': '1', + 'maxOccurs': '1'} + contents = {'xsd': ['annotation', 'element', 'group', 'choice', 'sequence', + 'any']} tag = 'sequence' def __init__(self, parent): @@ -2212,8 +2272,9 @@ class Sequence(XMLSchemaComponent,\ self.content = tuple(content) -class All(XMLSchemaComponent,\ +class All(XMLSchemaComponent, AllMarker): + """ parents: complexType, extension, restriction, group @@ -2226,8 +2287,8 @@ class All(XMLSchemaComponent,\ annotation?, element* """ attributes = {'id': None, - 'minOccurs': '1', - 'maxOccurs': '1'} + 'minOccurs': '1', + 'maxOccurs': '1'} contents = {'xsd': ['annotation', 'element']} tag = 'all' @@ -2261,8 +2322,9 @@ class All(XMLSchemaComponent,\ self.content = tuple(content) -class Choice(XMLSchemaComponent,\ +class Choice(XMLSchemaComponent, ChoiceMarker): + """ parents: complexType, extension, restriction, group, choice, sequence @@ -2275,10 +2337,10 @@ class Choice(XMLSchemaComponent,\ annotation?, (element | group | choice | sequence | any)* """ attributes = {'id': None, - 'minOccurs': '1', - 'maxOccurs': '1'} - contents = {'xsd': ['annotation', 'element', 'group', 'choice', 'sequence',\ - 'any']} + 'minOccurs': '1', + 'maxOccurs': '1'} + contents = {'xsd': ['annotation', 'element', 'group', 'choice', 'sequence', + 'any']} tag = 'choice' def __init__(self, parent): @@ -2319,9 +2381,10 @@ class Choice(XMLSchemaComponent,\ self.content = tuple(content) -class ModelGroupDefinition(XMLSchemaComponent,\ - ModelGroupMarker,\ +class ModelGroupDefinition(XMLSchemaComponent, + ModelGroupMarker, DefinitionMarker): + """ parents: redefine, schema @@ -2334,7 +2397,7 @@ class ModelGroupDefinition(XMLSchemaComponent,\ """ required = ['name'] attributes = {'id': None, - 'name': None} + 'name': None} contents = {'xsd': ['annotation', 'all', 'choice', 'sequence']} tag = 'group' @@ -2367,9 +2430,10 @@ class ModelGroupDefinition(XMLSchemaComponent,\ raise SchemaError('Unknown component (%s)' % (i.getTagName())) -class ModelGroupReference(XMLSchemaComponent,\ - ModelGroupMarker,\ +class ModelGroupReference(XMLSchemaComponent, + ModelGroupMarker, ReferenceMarker): + """ parents: choice, complexType, extension, restriction, sequence @@ -2384,9 +2448,9 @@ class ModelGroupReference(XMLSchemaComponent,\ """ required = ['ref'] attributes = {'id': None, - 'ref': None, - 'minOccurs': '1', - 'maxOccurs': '1'} + 'ref': None, + 'minOccurs': '1', + 'maxOccurs': '1'} contents = {'xsd': ['annotation']} tag = 'group' @@ -2413,9 +2477,10 @@ class ModelGroupReference(XMLSchemaComponent,\ raise SchemaError('Unknown component (%s)' % (i.getTagName())) -class ComplexType(XMLSchemaComponent,\ - DefinitionMarker,\ +class ComplexType(XMLSchemaComponent, + DefinitionMarker, ComplexMarker): + """ parents: redefine, schema @@ -2433,14 +2498,14 @@ class ComplexType(XMLSchemaComponent,\ """ required = ['name'] attributes = {'id': None, - 'name': None, - 'mixed': 0, - 'abstract': 0, - 'block': lambda self: self._parent().getBlockDefault(), - 'final': lambda self: self._parent().getFinalDefault()} - contents = {'xsd': ['annotation', 'simpleContent', 'complexContent',\ - 'group', 'all', 'choice', 'sequence', 'attribute', 'attributeGroup',\ - 'anyAttribute', 'any']} + 'name': None, + 'mixed': 0, + 'abstract': 0, + 'block': lambda self: self._parent().getBlockDefault(), + 'final': lambda self: self._parent().getFinalDefault()} + contents = {'xsd': ['annotation', 'simpleContent', 'complexContent', + 'group', 'all', 'choice', 'sequence', 'attribute', 'attributeGroup', + 'anyAttribute', 'any']} tag = 'complexType' def __init__(self, parent): @@ -2472,7 +2537,7 @@ class ComplexType(XMLSchemaComponent,\ def fromDom(self, node): self.setAttributes(node) - contents = self.getContents(node) + contents = list(self.getContents(node)) indx = 0 num = len(contents) @@ -2526,6 +2591,7 @@ class ComplexType(XMLSchemaComponent,\ indx += 1 class _DerivedType(XMLSchemaComponent): + def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) self.annotation = None @@ -2555,8 +2621,9 @@ class ComplexType(XMLSchemaComponent,\ self.derivation.fromDom(i) self.content = self.derivation - class ComplexContent(_DerivedType,\ + class ComplexContent(_DerivedType, ComplexMarker): + """ parents: complexType @@ -2568,7 +2635,7 @@ class ComplexType(XMLSchemaComponent,\ annotation?, (restriction | extension) """ attributes = {'id': None, - 'mixed': 0} + 'mixed': 0} contents = {'xsd': ['annotation', 'restriction', 'extension']} tag = 'complexContent' @@ -2584,6 +2651,7 @@ class ComplexType(XMLSchemaComponent,\ raise SchemaError('invalid value for attribute mixed(%s): %s' % (m, self.getItemTrace())) class _DerivationBase(XMLSchemaComponent): + """, parents: complexContent @@ -2597,9 +2665,9 @@ class ComplexType(XMLSchemaComponent,\ """ required = ['base'] attributes = {'id': None, - 'base': None} - contents = {'xsd': ['annotation', 'group', 'all', 'choice',\ - 'sequence', 'attribute', 'attributeGroup', 'anyAttribute']} + 'base': None} + contents = {'xsd': ['annotation', 'group', 'all', 'choice', + 'sequence', 'attribute', 'attributeGroup', 'anyAttribute']} def __init__(self, parent): XMLSchemaComponent.__init__(self, parent) @@ -2667,6 +2735,7 @@ class ComplexType(XMLSchemaComponent,\ class Extension(_DerivationBase, ExtensionMarker): + """ parents: complexContent @@ -2680,8 +2749,9 @@ class ComplexType(XMLSchemaComponent,\ """ tag = 'extension' - class Restriction(_DerivationBase,\ + class Restriction(_DerivationBase, RestrictionMarker): + """ parents: complexContent @@ -2695,8 +2765,9 @@ class ComplexType(XMLSchemaComponent,\ """ tag = 'restriction' - class SimpleContent(_DerivedType,\ + class SimpleContent(_DerivedType, SimpleMarker): + """ parents: complexType @@ -2710,8 +2781,9 @@ class ComplexType(XMLSchemaComponent,\ contents = {'xsd': ['annotation', 'restriction', 'extension']} tag = 'simpleContent' - class Extension(XMLSchemaComponent,\ + class Extension(XMLSchemaComponent, ExtensionMarker): + """ parents: simpleContent @@ -2724,9 +2796,9 @@ class ComplexType(XMLSchemaComponent,\ """ required = ['base'] attributes = {'id': None, - 'base': None} + 'base': None} contents = {'xsd': ['annotation', 'attribute', 'attributeGroup', - 'anyAttribute']} + 'anyAttribute']} tag = 'extension' def __init__(self, parent): @@ -2770,8 +2842,9 @@ class ComplexType(XMLSchemaComponent,\ indx += 1 self.attr_content = tuple(content) - class Restriction(XMLSchemaComponent,\ + class Restriction(XMLSchemaComponent, RestrictionMarker): + """ parents: simpleContent @@ -2788,9 +2861,9 @@ class ComplexType(XMLSchemaComponent,\ """ required = ['base'] attributes = {'id': None, - 'base': None} - contents = {'xsd': ['annotation', 'simpleType', 'attribute',\ - 'attributeGroup', 'anyAttribute'] + RestrictionMarker.facets} + 'base': None} + contents = {'xsd': ['annotation', 'simpleType', 'attribute', + 'attributeGroup', 'anyAttribute'] + RestrictionMarker.facets} tag = 'restriction' def __init__(self, parent): @@ -2838,8 +2911,9 @@ class ComplexType(XMLSchemaComponent,\ self.attr_content = tuple(content) -class LocalComplexType(ComplexType,\ +class LocalComplexType(ComplexType, LocalMarker): + """ parents: element @@ -2853,13 +2927,14 @@ class LocalComplexType(ComplexType,\ """ required = [] attributes = {'id': None, - 'mixed': 0} + 'mixed': 0} tag = 'complexType' -class SimpleType(XMLSchemaComponent,\ - DefinitionMarker,\ +class SimpleType(XMLSchemaComponent, + DefinitionMarker, SimpleMarker): + """ parents: redefine, schema @@ -2874,8 +2949,8 @@ class SimpleType(XMLSchemaComponent,\ """ required = ['name'] attributes = {'id': None, - 'name': None, - 'final': lambda self: self._parent().getFinalDefault()} + 'name': None, + 'final': lambda self: self._parent().getFinalDefault()} contents = {'xsd': ['annotation', 'restriction', 'list', 'union']} tag = 'simpleType' @@ -2912,8 +2987,9 @@ class SimpleType(XMLSchemaComponent,\ raise SchemaError('Unknown component (%s)' % (component)) self.content.fromDom(child) - class Restriction(XMLSchemaComponent,\ + class Restriction(XMLSchemaComponent, RestrictionMarker): + """ parents: simpleType @@ -2928,7 +3004,7 @@ class SimpleType(XMLSchemaComponent,\ totalDigits | whiteSpace)* """ attributes = {'id': None, - 'base': None} + 'base': None} contents = {'xsd': ['annotation', 'simpleType'] + RestrictionMarker.facets} tag = 'restriction' @@ -2973,6 +3049,7 @@ class SimpleType(XMLSchemaComponent,\ class Union(XMLSchemaComponent, UnionMarker): + """ parents: simpleType @@ -2984,7 +3061,7 @@ class SimpleType(XMLSchemaComponent,\ annotation?, simpleType* """ attributes = {'id': None, - 'memberTypes': None} + 'memberTypes': None} contents = {'xsd': ['annotation', 'simpleType']} tag = 'union' @@ -3012,6 +3089,7 @@ class SimpleType(XMLSchemaComponent,\ class List(XMLSchemaComponent, ListMarker): + """ parents: simpleType @@ -3023,7 +3101,7 @@ class SimpleType(XMLSchemaComponent,\ annotation?, simpleType? """ attributes = {'id': None, - 'itemType': None} + 'itemType': None} contents = {'xsd': ['annotation', 'simpleType']} tag = 'list' @@ -3062,9 +3140,10 @@ class SimpleType(XMLSchemaComponent,\ raise SchemaError('Unknown component (%s)' % (i.getTagName())) -class AnonymousSimpleType(SimpleType,\ - SimpleMarker,\ +class AnonymousSimpleType(SimpleType, + SimpleMarker, LocalMarker): + """ parents: attribute, element, list, restriction, union @@ -3080,6 +3159,7 @@ class AnonymousSimpleType(SimpleType,\ class Redefine: + """ parents: attributes: @@ -3101,6 +3181,7 @@ else: class TypeDescriptionComponent(tupleClass): + """Tuple of length 2, consisting of a namespace and unprefixed name. """ diff --git a/wstools/XMLname.py b/wstools/XMLname.py index a584a57..615dc2f 100644 --- a/wstools/XMLname.py +++ b/wstools/XMLname.py @@ -72,9 +72,9 @@ def toXMLname(string): if i < N - 1 and T[i] == u'_' and T[i + 1] == u'x': X.append(u'_x005F_') elif i == 0 and N >= 3 and \ - (T[0] == u'x' or T[0] == u'X') and \ - (T[1] == u'm' or T[1] == u'M') and \ - (T[2] == u'l' or T[2] == u'L'): + (T[0] == u'x' or T[0] == u'X') and \ + (T[1] == u'm' or T[1] == u'M') and \ + (T[2] == u'l' or T[2] == u'L'): X.append(u'_xFFFF_' + T[0]) elif (not _NCNameChar(T[i])) or (i == 0 and not _NCNameStartChar(T[i])): X.append(_toUnicodeHex(T[i])) diff --git a/wstools/c14n.py b/wstools/c14n.py index 462fc4c..7e9dcb1 100644 --- a/wstools/c14n.py +++ b/wstools/c14n.py @@ -101,8 +101,8 @@ def _utilized(n, node, other_attrs, unsuppressedPrefixes): elif n.startswith('xmlns'): n = n[5:] if (n == "" and node.prefix in ["#default", None]) or \ - n == node.prefix or n in unsuppressedPrefixes: - return 1 + n == node.prefix or n in unsuppressedPrefixes: + return 1 for attr in other_attrs: if n == attr.prefix: return 1 @@ -151,6 +151,7 @@ _in_subset = lambda subset, node: subset is None or node in subset # rich's twe class _implementation: + '''Implementation class for C14N. This accompanies a node during it's processing and includes the parameters and processing state.''' @@ -174,7 +175,7 @@ class _implementation: self.documentOrder = _Element # At document element if not _inclusive(self): inherited, unused = _inclusiveNamespacePrefixes(node, self._inherit_context(node), - self.unsuppressedPrefixes) + self.unsuppressedPrefixes) self._do_element(node, inherited, unused=unused) else: inherited = self._inherit_context(node) @@ -311,7 +312,7 @@ class _implementation: # xml_attrs_local -- Local attributes in XML namespace. # ns_unused_inherited -- not rendered namespaces, used for exclusive ns_parent, ns_rendered, xml_attrs = \ - self.state[0], self.state[1].copy(), self.state[2].copy() # 0422 + self.state[0], self.state[1].copy(), self.state[2].copy() # 0422 ns_unused_inherited = unused if unused is None: @@ -372,14 +373,14 @@ class _implementation: # If default namespace is XMLNS.BASE or empty, # and if an ancestor was the same if n == "xmlns" and v in [XMLNS.BASE, ''] \ - and ns_rendered.get('xmlns') in [XMLNS.BASE, '', None]: + and ns_rendered.get('xmlns') in [XMLNS.BASE, '', None]: continue # "omit namespace node with local name xml, which defines # the xml prefix, if its string value is # http://www.w3.org/XML/1998/namespace." if n in ["xmlns:xml", "xml"] \ - and v in ['http://www.w3.org/XML/1998/namespace']: + and v in ['http://www.w3.org/XML/1998/namespace']: continue # If not previously rendered diff --git a/wstools/version.py b/wstools/version.py index f6b7e26..cd1ee63 100644 --- a/wstools/version.py +++ b/wstools/version.py @@ -1 +1 @@ -__version__ = "0.4.3" +__version__ = "0.4.4"