Signed-off-by: Sorin Sbarnea <sorin.sbarnea@gmail.com>main
@@ -5,3 +5,6 @@ dist | |||
.tox | |||
~*.* | |||
build/ | |||
.idea/inspectionProfiles/ | |||
.python-version | |||
.vscode |
@@ -0,0 +1 @@ | |||
wstools |
@@ -0,0 +1,5 @@ | |||
<atlassian-ide-plugin> | |||
<project-configuration id="1"> | |||
<servers id="2" /> | |||
</project-configuration> | |||
</atlassian-ide-plugin> |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="Encoding"> | |||
<file url="PROJECT" charset="UTF-8" /> | |||
</component> | |||
</project> |
@@ -0,0 +1,17 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="ProjectLevelVcsManager" settingsEditedManually="false"> | |||
<OptionsSetting value="true" id="Add" /> | |||
<OptionsSetting value="true" id="Remove" /> | |||
<OptionsSetting value="true" id="Checkout" /> | |||
<OptionsSetting value="true" id="Update" /> | |||
<OptionsSetting value="true" id="Status" /> | |||
<OptionsSetting value="true" id="Edit" /> | |||
<ConfirmationsSetting value="0" id="Add" /> | |||
<ConfirmationsSetting value="0" id="Remove" /> | |||
</component> | |||
<component name="ProjectRootManager" version="2" project-jdk-name="python" project-jdk-type="Python SDK" /> | |||
<component name="UnicodeBrowser"> | |||
<option name="fontName" value="Menlo" /> | |||
</component> | |||
</project> |
@@ -0,0 +1,8 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="ProjectModuleManager"> | |||
<modules> | |||
<module fileurl="file://$PROJECT_DIR$/.idea/wstools.iml" filepath="$PROJECT_DIR$/.idea/wstools.iml" /> | |||
</modules> | |||
</component> | |||
</project> |
@@ -0,0 +1,6 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<project version="4"> | |||
<component name="VcsDirectoryMappings"> | |||
<mapping directory="$PROJECT_DIR$" vcs="Git" /> | |||
</component> | |||
</project> |
@@ -4,11 +4,12 @@ os: | |||
- linux | |||
python: | |||
- '2.7' | |||
- '3.3' | |||
- '3.4' | |||
- '3.5' | |||
install: | |||
- pip -q install coveralls six autopep8 | |||
script: | |||
- pip -q install -r requirements.txt | |||
- pip -q install -r requirements-dev.txt | |||
script: | |||
- curl --silent -Lo travis_after_all.py https://raw.github.com/pycontribs/travis_after_all/master/travis_after_all.py && travis_wait python setup.py prerelease test | |||
- export PACKAGE_VERSION=$(python -c "from wstools.version import __version__; print(__version__)") | |||
after_success: | |||
@@ -40,20 +41,34 @@ after_script: | |||
branches: | |||
only: | |||
- master | |||
- develop | |||
before_deploy: | |||
- echo "before deploy..." | |||
deploy: | |||
- provider: releases | |||
api_key: | |||
- secure: "gr9iOcQjdoAyUAim6FWKzJI9MBaJo9XKfGQGu7wdPXUFhg80Rp6GLJsowP+aU94NjXM1UQlVHDAy627WtjBlLH2SvmVEIIr7+UKBopBYuXG5jJ1m3wOZE+4f1Pqe9bqFc1DxgucqE8qF0sC24fIbNM2ToeyYrxrS6RoL2gRrX2I=" | |||
file: "dist/jira-$PACKAGE_VERSION.tar.gz" | |||
file: "dist/wstools-$PACKAGE_VERSION.tar.gz" | |||
skip_cleanup: true | |||
on: | |||
branch: master | |||
condition: "$BUILD_LEADER = YES" | |||
tags: true | |||
- provider: pypi | |||
user: sorin | |||
password: | |||
secure: "E0cjANF7SLBdYrsnWLK8X/xWznqkF0JrP/DVfDazPzUYH6ynFeneyofzNJQPLTLsqe1eKXhuUJ/Sbl+RHFB0ySo/j/7NfYd/9pm8hpUkGCvR09IwtvMLgWKp3k10NWab03o2GOkSJSrLvZofyZBGR40wwu2O9uXPCb2rvucCGbw=" | |||
distributions: "sdist bdist_wheel" | |||
on: | |||
branch: master | |||
condition: "$BUILD_LEADER = YES" | |||
- provider: pypi | |||
server: https://testpypi.python.org/pypi | |||
user: sorins | |||
password: | |||
secure: "E0cjANF7SLBdYrsnWLK8X/xWznqkF0JrP/DVfDazPzUYH6ynFeneyofzNJQPLTLsqe1eKXhuUJ/Sbl+RHFB0ySo/j/7NfYd/9pm8hpUkGCvR09IwtvMLgWKp3k10NWab03o2GOkSJSrLvZofyZBGR40wwu2O9uXPCb2rvucCGbw=" | |||
distributions: "sdist bdist_wheel" | |||
on: | |||
branch: develop | |||
tags: false | |||
condition: "$BUILD_LEADER = YES" |
@@ -0,0 +1,67 @@ | |||
all: clean flake8 test pypi docs tag release | |||
.PHONY: all docs | |||
PACKAGE_NAME=$(shell python setup.py --name) | |||
PYTHON_VERSION=$(shell python -c "import sys; print('py%s%s' % sys.version_info[0:2])") | |||
PYTHON_PATH=$(shell which python) | |||
PLATFORM=$(shell uname -s | awk '{print tolower($0)}') | |||
DIR:=$(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) | |||
PYENV_HOME := $(DIR)/.tox/$(PYTHON_VERSION)-$(PLATFORM)/ | |||
clean: | |||
find . -name "*.pyc" -delete | |||
package: | |||
python setup.py sdist bdist_wheel build_sphinx | |||
install: prepare | |||
$(PYENV_HOME)/bin/python setup.py install | |||
uninstall: | |||
$(PYENV_HOME)/bin/pip uninstall -y $(PACKAGE_NAME) | |||
venv: $(PYENV_HOME)/bin/activate | |||
# virtual environment depends on requriements files | |||
$(PYENV_HOME)/bin/activate: requirements*.txt | |||
@echo "INFO: (Re)creating virtual environment..." | |||
test -d $(PYENV_HOME)/bin/activate || virtualenv --python=$(PYTHON_PATH) --system-site-packages $(PYENV_HOME) | |||
$(PYENV_HOME)/bin/pip install -q -r requirements.txt | |||
$(PYENV_HOME)/bin/pip install -q -r requirements-dev.txt | |||
touch $(PYENV_HOME)/bin/activate | |||
prepare: venv | |||
@echo "INFO: === Prearing to run for package:$(PACKAGE_NAME) platform:$(PLATFORM) py:$(PYTHON_VERSION) dir:$(DIR) ===" | |||
testspace: | |||
${HOME}/testspace/testspace publish build/results.xml | |||
flake8: | |||
$(PYENV_HOME)/bin/python -m flake8 | |||
$(PYENV_HOME)/bin/python -m flake8 --install-hook 2>/dev/null || true | |||
test: prepare flake8 | |||
$(PYENV_HOME)/bin/python setup.py test | |||
test-all: | |||
# tox should not run inside virtualenv because it does create and use multiple virtualenvs | |||
pip install -q tox tox-pyenv | |||
python -m tox --skip-missing-interpreters true | |||
pypi: | |||
$(PYENV_HOME)/bin/python setup.py check --restructuredtext --strict | |||
$(PYENV_HOME)/bin/python setup.py sdist bdist_wheel upload | |||
pypitest: | |||
$(PYENV_HOME)/bin/python setup.py check --restructuredtext --strict | |||
$(PYENV_HOME)/bin/python setup.py sdist bdist_wheel upload -r pypitest | |||
tag: | |||
bumpversion minor | |||
git push origin master | |||
git push --tags | |||
release: | |||
tag | |||
pypi | |||
web |
@@ -5,7 +5,7 @@ VERSION=$(python -c "from wstools.version import __version__ ; print __version__ | |||
echo Preparing to release version $VERSION | |||
echo === Chechink that all changes are commited and pushed === | |||
git pull -u | |||
git pull | |||
git diff | |||
# Disallow unstaged changes in the working tree | |||
@@ -0,0 +1,9 @@ | |||
autopep8 | |||
coverage | |||
coveralls | |||
flake8 | |||
flake8-docstrings>=0.2.8 | |||
flake8-pep257>=1.0.5 | |||
nose | |||
pytest | |||
pytest-flake8 |
@@ -0,0 +1 @@ | |||
six |
@@ -15,7 +15,7 @@ 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 | |||
addopts = -p no:xdist --ignore=setup.py --tb=long -rsxX -v --maxfail=10 --flake8 tests | |||
timeout=60 | |||
# --maxfail=2 -n4 | |||
# -n4 runs up to 4 parallel procs | |||
@@ -25,22 +25,11 @@ timeout=60 | |||
# 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 | |||
flake8-max-line-length = 99 | |||
flake8-ignore = D D100 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 | |||
[flake8] | |||
max-line-length=160 | |||
exclude=build | |||
statistics=yes | |||
ignore = D,E402 |
@@ -37,7 +37,7 @@ class PyTest(TestCommand): | |||
# if we have pytest-cache module we enable the test failures first mode | |||
try: | |||
import pytest_cache | |||
import pytest_cache # noqa | |||
self.pytest_args.append("--ff") | |||
except ImportError: | |||
pass | |||
@@ -47,7 +47,7 @@ class PyTest(TestCommand): | |||
# when run manually we enable fail fast | |||
self.pytest_args.append("--maxfail=1") | |||
try: | |||
import coveralls | |||
import coveralls # noqa | |||
self.pytest_args.append("--cov=%s" % NAME) | |||
self.pytest_args.extend(["--cov-report", "term"]) | |||
self.pytest_args.extend(["--cov-report", "xml"]) | |||
@@ -63,14 +63,14 @@ class PyTest(TestCommand): | |||
def run_tests(self): | |||
# before running tests we need to run autopep8 | |||
try: | |||
r = subprocess.check_call( | |||
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 | |||
import pytest # noqa | |||
errno = pytest.main(self.pytest_args) | |||
sys.exit(errno) | |||
@@ -98,7 +98,8 @@ class Release(Command): | |||
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) | |||
"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)) | |||
@@ -163,8 +164,8 @@ setup( | |||
'License :: OSI Approved :: BSD License', | |||
'Operating System :: OS Independent', | |||
'Topic :: Software Development :: Libraries :: Python Modules', | |||
'Programming Language :: Python :: 3.3', | |||
'Programming Language :: Python :: 3.4', | |||
'Programming Language :: Python :: 3.5', | |||
'Topic :: Internet :: WWW/HTTP', | |||
], | |||
) |
@@ -13,9 +13,9 @@ 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 | |||
from wstools.Utility import DOM # noqa E402 | |||
from wstools.WSDLTools import WSDLReader # noqa E402 | |||
from wstools.TimeoutSocket import TimeoutError # noqa E402 | |||
try: | |||
import configparser | |||
except: | |||
@@ -49,7 +49,7 @@ class WSDLToolsTestCase(unittest.TestCase): | |||
self.path = nameGenerator.__next__() | |||
else: | |||
self.path = nameGenerator.next() | |||
#print(self.path) | |||
# print(self.path) | |||
sys.stdout.flush() | |||
def __str__(self): | |||
@@ -67,7 +67,7 @@ class WSDLToolsTestCase(unittest.TestCase): | |||
nspname = DOM.GetWSDLUri(version) | |||
for node in DOM.getElements(definition, tag_name, nspname): | |||
name = DOM.getAttr(node, key) | |||
comp = component[name] | |||
comp = component[name] # noqa F841 | |||
self.failUnlessEqual(eval('comp.%s' % key), name) | |||
def checkXSDCollection(self, tag_name, component, node, key='name'): | |||
@@ -1,25 +1,20 @@ | |||
[tox] | |||
minversion = 1.3 | |||
envlist = py27,py34,flake8 | |||
minversion = 2.3.1 | |||
envlist = {py27,py34,py35}-{win,linux,darwin} | |||
addopts = --ignore=setup.py | |||
skip_missing_interpreters = true | |||
tox_pyenv_fallback=True | |||
[testenv] | |||
deps= | |||
nose | |||
coveralls | |||
coverage | |||
commands= | |||
nosetests --with-coverage --cover-package=wstools | |||
bash -c "coveralls || true" | |||
whitelist_externals=bash | |||
[testenv:py27] | |||
[testenv:py33] | |||
sitepackages=True | |||
platform = | |||
win: windows | |||
linux: linux | |||
darwin: darwin | |||
[testenv:py34] | |||
[testenv:flake8] | |||
basepython=python2.7 | |||
deps=flake8 | |||
commands=flake8 wstools/ | |||
deps= | |||
-rrequirements.txt | |||
-rrequirements-dev.txt | |||
commands= | |||
python -m py.test --cov-report xml |
@@ -15,13 +15,15 @@ | |||
ident = "$Id$" | |||
import types | |||
import weakref | |||
import logging | |||
import sys | |||
import types | |||
import warnings | |||
import logging | |||
from .Namespaces import SCHEMA, XMLNS, SOAP, APACHE | |||
from .Utility import DOM, DOMException, Collection, SplitQName, basejoin | |||
import weakref | |||
from .Namespaces import APACHE, SCHEMA, SOAP, XMLNS | |||
from .Utility import DOM, Collection, DOMException, SplitQName, basejoin | |||
try: | |||
from StringIO import StringIO | |||
except: | |||
@@ -110,7 +112,7 @@ class SchemaReader: | |||
""" | |||
reader = self.__readerClass(element) | |||
schema = XMLSchema(parent) | |||
#HACK to keep a reference | |||
# HACK to keep a reference | |||
schema.wsdl = parent | |||
schema.setBaseUrl(self.__base_url) | |||
schema.load(reader) | |||
@@ -771,7 +773,7 @@ class XMLSchemaComponent(XMLBase, MarkerInterface): | |||
ns = node.getNamespace(prefix) | |||
if not ns: | |||
raise SchemaError('no namespace for attribute prefix %s' % prefix) | |||
if not ns in self.attributes: | |||
if ns not in self.attributes: | |||
self.attributes[ns] = {} | |||
elif value in self.attributes[ns]: | |||
raise SchemaError('attribute %s declared multiple times in %s' % (value, ns)) | |||
@@ -785,14 +787,14 @@ class XMLSchemaComponent(XMLBase, MarkerInterface): | |||
self.__checkAttributes() | |||
self.__setAttributeDefaults() | |||
#set QNames | |||
# set QNames | |||
for k in ['type', 'element', 'base', 'ref', 'substitutionGroup', 'itemType']: | |||
if k in self.attributes: | |||
prefix, value = SplitQName(self.attributes.get(k)) | |||
self.attributes[k] = \ | |||
TypeDescriptionComponent((self.getXMLNS(prefix), value)) | |||
#Union, memberTypes is a whitespace separated list of QNames | |||
# Union, memberTypes is a whitespace separated list of QNames | |||
for k in ['memberTypes']: | |||
if k in self.attributes: | |||
qnames = self.attributes[k] | |||
@@ -1273,17 +1275,17 @@ class XMLSchema(XMLSchemaComponent): | |||
del slocd[import_ns] | |||
continue | |||
except SchemaError as ex: | |||
#warnings.warn(\ | |||
# '<import namespace="%s" schemaLocation=?>, %s'\ | |||
# %(import_ns, 'failed to load schema instance') | |||
#) | |||
# warnings.warn(\ | |||
# '<import namespace="%s" schemaLocation=?>, %s'\ | |||
# %(import_ns, 'failed to load schema instance') | |||
# ) | |||
self.logger.debug(ex) | |||
del slocd[import_ns] | |||
class _LazyEvalImport(str): | |||
'''Lazy evaluation of import, replace entry in self.imports.''' | |||
#attributes = dict(namespace=import_ns) | |||
# attributes = dict(namespace=import_ns) | |||
def getSchema(namespace): | |||
schema = slocd.get(namespace) | |||
if schema is None: | |||
@@ -1417,7 +1419,7 @@ class XMLSchema(XMLSchemaComponent): | |||
reader._includes = self._parent().getIncludeSchemas() | |||
self._schema = schema | |||
if not 'schemaLocation' in self.attributes: | |||
if 'schemaLocation' not in self.attributes: | |||
raise NoSchemaLocationWarning('no schemaLocation attribute in import') | |||
reader.loadFromURL(self.attributes.get('schemaLocation'), schema) | |||
@@ -2684,7 +2686,7 @@ class ComplexType(XMLSchemaComponent, | |||
indx = 0 | |||
num = len(contents) | |||
#XXX ugly | |||
# XXX ugly | |||
if not num: | |||
return | |||
component = SplitQName(contents[indx].getTagName())[1] | |||
@@ -3044,7 +3046,7 @@ class SimpleType(XMLSchemaComponent, | |||
elif component in RestrictionMarker.facets: | |||
self.facets.append(contents[indx]) | |||
else: | |||
raise SchemaError('Unknown component (%s)' % (i.getTagName())) | |||
raise SchemaError('Unknown component (%s)' % (contents[indx].getTagName())) | |||
self.content = tuple(content) | |||
class Union(XMLSchemaComponent, | |||
@@ -3084,7 +3086,7 @@ class SimpleType(XMLSchemaComponent, | |||
content.append(AnonymousSimpleType(self)) | |||
content[-1].fromDom(contents[indx]) | |||
else: | |||
raise SchemaError('Unknown component (%s)' % (i.getTagName())) | |||
raise SchemaError('Unknown component (%s)' % (contents[indx].getTagName())) | |||
self.content = tuple(content) | |||
class List(XMLSchemaComponent, | |||
@@ -3137,7 +3139,7 @@ class SimpleType(XMLSchemaComponent, | |||
self.content.fromDom(contents[indx]) | |||
break | |||
else: | |||
raise SchemaError('Unknown component (%s)' % (i.getTagName())) | |||
raise SchemaError('Unknown component (%s)' % (contents[indx].getTagName())) | |||
class AnonymousSimpleType(SimpleType, | |||
@@ -1,3 +1,5 @@ | |||
import re | |||
"""Translate strings to and from SOAP 1.2 XML name encoding | |||
Implements rules for mapping application defined name to XML names | |||
@@ -15,8 +17,6 @@ Version 0.9.0 | |||
ident = "$Id$" | |||
from re import * | |||
def _NCNameChar(x): | |||
return x.isalpha() or x.isdigit() or x == "." or x == '-' or x == "_" | |||
@@ -89,11 +89,11 @@ def toXMLname(string): | |||
def fromXMLname(string): | |||
"""Convert XML name to unicode string.""" | |||
retval = sub(r'_xFFFF_', '', string) | |||
retval = re.sub(r'_xFFFF_', '', string) | |||
def fun(matchobj): | |||
return _fromUnicodeHex(matchobj.group(0)) | |||
retval = sub(r'_x[0-9A-Fa-f]{4}_', fun, retval) | |||
retval = re.sub(r'_x[0-9A-Fa-f]{4}_', fun, retval) | |||
return retval |
@@ -3,5 +3,5 @@ | |||
ident = "$Id$" | |||
from . import WSDLTools | |||
from . import XMLname | |||
from . import WSDLTools # noqa | |||
from . import XMLname # noqa |
@@ -1,4 +1,19 @@ | |||
#! /usr/bin/env python | |||
import string | |||
import sys | |||
from xml.dom import Node | |||
try: | |||
from xml.ns import XMLNS | |||
except: | |||
class XMLNS: | |||
BASE = "http://www.w3.org/2000/xmlns/" | |||
XML = "http://www.w3.org/XML/1998/namespace" | |||
try: | |||
from io import StringIO | |||
except ImportError: | |||
from cStringIO import StringIO | |||
'''XML Canonicalization | |||
Patches Applied to xml.dom.ext.c14n: | |||
@@ -47,30 +62,31 @@ or | |||
http://www.w3.org/Consortium/Legal/copyright-software-19980720 | |||
''' | |||
import string | |||
from xml.dom import Node | |||
try: | |||
from xml.ns import XMLNS | |||
except: | |||
class XMLNS: | |||
BASE = "http://www.w3.org/2000/xmlns/" | |||
XML = "http://www.w3.org/XML/1998/namespace" | |||
try: | |||
from io import StringIO | |||
except ImportError: | |||
from cStringIO import StringIO | |||
def _attrs(E): | |||
return (E.attributes and list(E.attributes.values())) or [] | |||
def _children(E): | |||
return E.childNodes or [] | |||
_attrs = lambda E: (E.attributes and list(E.attributes.values())) or [] | |||
_children = lambda E: E.childNodes or [] | |||
_IN_XML_NS = lambda n: n.name.startswith("xmlns") | |||
_inclusive = lambda n: n.unsuppressedPrefixes is None | |||
def _IN_XML_NS(n): | |||
return n.name.startswith("xmlns") | |||
def _inclusive(n): | |||
return n.unsuppressedPrefixes is None | |||
# Does a document/PI has lesser/greater document order than the | |||
# first element? | |||
_LesserElement, _Element, _GreaterElement = list(range(3)) | |||
if sys.version_info[0] > 2: | |||
def cmp(a, b): | |||
return (a > b) - (a < b) | |||
def _sorter(n1, n2): | |||
'''_sorter(n1,n2) -> int | |||
@@ -146,8 +162,10 @@ def _inclusiveNamespacePrefixes(node, context, unsuppressedPrefixes): | |||
return inclusive, unused_namespace_dict | |||
#_in_subset = lambda subset, node: not subset or node in subset | |||
_in_subset = lambda subset, node: subset is None or node in subset # rich's tweak | |||
# _in_subset = lambda subset, node: not subset or node in subset | |||
def _in_subset(subset, node): | |||
return subset is None or node in subset # rich's tweak | |||
class _implementation: | |||
@@ -342,7 +360,7 @@ class _implementation: | |||
# if not inclusive and a.prefix is not None and not ns_rendered.has_key('xmlns:%s' %a.prefix): | |||
# ns_local['xmlns:%s' %a.prefix] = ?? | |||
#add local xml:foo attributes to ancestor's xml:foo attributes | |||
# add local xml:foo attributes to ancestor's xml:foo attributes | |||
xml_attrs.update(xml_attrs_local) | |||
# Render the node | |||
@@ -356,7 +374,7 @@ class _implementation: | |||
prefix = 'xmlns' | |||
if prefix not in ns_rendered and prefix not in ns_local: | |||
if not prefix in ns_unused_inherited: | |||
if prefix not in ns_unused_inherited: | |||
raise RuntimeError('For exclusive c14n, unable to map prefix "%s" in %s' % ( | |||
prefix, node)) | |||
@@ -1 +1 @@ | |||
__version__ = "0.4.4" | |||
__version__ = "0.4.5" |