Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ before_install:
install:
- pip install -r requirements.txt -r requirements-test.txt --use-mirrors
- if [[ $USE_OPTIONAL == "true" ]]; then pip install -r requirements-optional.txt --use-mirrors; fi
- if [[ $TRAVIS_PYTHON_VERSION == "2.6" && $USE_OPTIONAL == "true" ]]; then pip install -r requirements-optional-2.6.txt --use-mirrors; fi
- if [[ $TRAVIS_PYTHON_VERSION != "pypy" && $USE_OPTIONAL == "true" ]]; then pip install -r requirements-optional-cpython.txt --use-mirrors; fi
- if [[ $FLAKE == "true" ]]; then pip install --use-mirrors flake8; fi

Expand Down
8 changes: 7 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ Optionally:
be determined; ``chardet``, from which it was forked, can also be used
on Python 2.

- ``ordereddict`` can be used under Python 2.6
(``collections.OrderedDict`` is used instead on later versions) to
serialize attributes in alphabetical order.


Installation
------------
Expand Down Expand Up @@ -78,7 +82,9 @@ release tarballs this is unneeded)::
$ git submodule update

And then they can be run, with ``nose`` installed, using the
``nosetests`` command in the root directory. All should pass.
``nosetests`` command in the root directory. Note that ``ordereddict``
is required for the serializer tests under Python 2.6. All should
pass.

If you have all compatible Python implementations available on your
system, you can run tests on all of them by using tox::
Expand Down
20 changes: 20 additions & 0 deletions html5lib/filters/alphabeticalattributes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from __future__ import absolute_import, division, unicode_literals

from . import _base

try:
from collections import OrderedDict
except ImportError:
from ordereddict import OrderedDict


class Filter(_base.Filter):
def __iter__(self):
for token in _base.Filter.__iter__(self):
if token["type"] in ("StartTag", "EmptyTag"):
attrs = OrderedDict()
for name, value in sorted(token["data"].items(),
key=lambda x: x[0]):
attrs[name] = value
token["data"] = attrs
yield token
2 changes: 1 addition & 1 deletion html5lib/serializer/htmlserializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def serialize(self, treewalker, encoding=None):
in_cdata = True
elif in_cdata:
self.serializeError(_("Unexpected child element of a CDATA element"))
for (attr_namespace, attr_name), attr_value in sorted(token["data"].items()):
for (attr_namespace, attr_name), attr_value in token["data"].items():
# TODO: Add namespace support here
k = attr_name
v = attr_value
Expand Down
4 changes: 3 additions & 1 deletion html5lib/tests/test_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import html5lib
from html5lib import serializer, constants
from html5lib.filters.alphabeticalattributes import Filter as AlphabeticalAttributesFilter
from html5lib.treewalkers._base import TreeWalker

optionals_loaded = []
Expand Down Expand Up @@ -84,7 +85,8 @@ def _convertAttrib(self, attribs):

def serialize_html(input, options):
options = dict([(str(k), v) for k, v in options.items()])
return serializer.HTMLSerializer(**options).render(JsonWalker(input), options.get("encoding", None))
stream = AlphabeticalAttributesFilter(JsonWalker(input))
return serializer.HTMLSerializer(**options).render(stream, options.get("encoding", None))


def runSerializerTest(input, expected, options):
Expand Down
3 changes: 3 additions & 0 deletions requirements-optional-2.6.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Can be used to force attributes to be serialized in alphabetical
# order.
ordereddict
1 change: 1 addition & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
nose
ordereddict # Python 2.6
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unnecessary since you're using requirements-optional-2.6.txt in Travis anyway.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only with USE_OPTIONAL=true; we also run with USE_OPTIONAL=false.

11 changes: 11 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,14 @@ deps =
six
commands =
{envbindir}/nosetests

[testenv:py26]
basepython = python2.6
deps =
charade
datrie
Genshi
lxml
ordereddict
nose
six