diff --git a/.appveyor.yml b/.appveyor.yml
index a1a3e347..8af60b9b 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -1,4 +1,4 @@
-# To activate, change the Appveyor settings to use `.appveyor.yml`.
+image: Visual Studio 2019
environment:
global:
PATH: "C:\\Python27\\Scripts\\;%PATH%"
@@ -13,6 +13,10 @@ environment:
- TOXENV: py37-optional
- TOXENV: py38-base
- TOXENV: py38-optional
+ - TOXENV: py39-base
+ - TOXENV: py39-optional
+ - TOXENV: py310-base
+ - TOXENV: py310-optional
install:
- git submodule update --init --recursive
diff --git a/.github/workflows/python-tox.yml b/.github/workflows/python-tox.yml
index ec5cf636..0e3e46db 100644
--- a/.github/workflows/python-tox.yml
+++ b/.github/workflows/python-tox.yml
@@ -6,15 +6,18 @@ jobs:
if: github.event.push || github.event.pull_request.head.repo.full_name != github.repository
runs-on: ubuntu-latest
strategy:
+ fail-fast: false
matrix:
- python: [2.7, 3.5, 3.6, 3.7, 3.8, pypy-2.7, pypy3]
+ python: ["2.7", "3.7", "3.8", "3.9", "3.10", "3.11", "pypy-2.7", "pypy-3.8"]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
submodules: true
- - uses: actions/setup-python@v2
+ - uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python }}
+ cache: pip
+ cache-dependency-path: "requirements*.txt"
- run: pip install tox
- run: tox -e py
- if: ${{ always() }}
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index d2d9e30e..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,25 +0,0 @@
-language: python
-python:
- - "pypy3"
- - "pypy"
- - "3.8"
- - "3.7"
- - "3.6"
- - "3.5"
- - "2.7"
- - "3.9-dev"
-
-cache: pip
-
-env:
- global:
- - TOXENV=base,optional,six19-optional
-
-install:
- - pip install tox
-
-script:
- - tox
-
-after_script:
- - python debug-info.py
diff --git a/CHANGES.rst b/CHANGES.rst
index 0f6314aa..3ed63a96 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -95,7 +95,7 @@ Released on July 14, 2016
tested, doesn't entirely work, and as far as I can tell is
completely unused by anyone.**
-* Move testsuite to ``py.test``.
+* Move testsuite to ``pytest``.
* **Fix #124: move to webencodings for decoding the input byte stream;
this makes html5lib compliant with the Encoding Standard, and
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 8c5e1985..dba35216 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -16,7 +16,7 @@ documentation. Some useful information:
- We keep the master branch passing all tests at all times on all
supported versions.
-`Travis CI `_ is run
+`GitHub Actions `_ is run
against all pull requests and should enforce all of the above.
We use `Opera Critic `_ as an external
diff --git a/README.rst b/README.rst
index d367905d..a17411ab 100644
--- a/README.rst
+++ b/README.rst
@@ -1,9 +1,8 @@
html5lib
========
-.. image:: http://travis-ci.org/html5lib/html5lib-python.svg?branch=master
- :target: http://travis-ci.org/html5lib/html5lib-python
-
+.. image:: http://github.com/html5lib/html5lib-python/actions/workflows/python-tox.yml/badge.svg
+ :target: http://github.com/html5lib/html5lib-python/actions/workflows/python-tox.yml
html5lib is a pure-python library for parsing HTML. It is designed to
conform to the WHATWG HTML specification, as is implemented by all major
@@ -128,7 +127,7 @@ Tests
-----
Unit tests require the ``pytest`` and ``mock`` libraries and can be
-run using the ``py.test`` command in the root directory.
+run using the ``pytest`` command in the root directory.
Test data are contained in a separate `html5lib-tests
`_ repository and included
@@ -145,7 +144,9 @@ which can be found on PyPI.
Questions?
----------
-There's a mailing list available for support on Google Groups,
-`html5lib-discuss `_,
-though you may get a quicker response asking on IRC in `#whatwg on
-irc.freenode.net `_.
+Check out `the docs http://html5lib.readthedocs.io/en/latest/`_. Still
+need help? Go to our `GitHub Discussions
+http://github.com/html5lib/html5lib-python/discussions`_.
+
+You can also browse the archives of the `html5lib-discuss mailing list
+http://www.mail-archive.com/html5lib-discuss@googlegroups.com/`_.
diff --git a/html5lib/_inputstream.py b/html5lib/_inputstream.py
index 0207dd21..a93b5a4e 100644
--- a/html5lib/_inputstream.py
+++ b/html5lib/_inputstream.py
@@ -324,7 +324,7 @@ def charsUntil(self, characters, opposite=False):
except KeyError:
if __debug__:
for c in characters:
- assert(ord(c) < 128)
+ assert ord(c) < 128
regex = "".join(["\\x%02x" % ord(c) for c in characters])
if not opposite:
regex = "^%s" % regex
diff --git a/html5lib/html5parser.py b/html5lib/html5parser.py
index 74d829d9..9fb038b7 100644
--- a/html5lib/html5parser.py
+++ b/html5lib/html5parser.py
@@ -1002,8 +1002,8 @@ def processCharacters(self, token):
self.tree.insertText(token["data"])
# This must be bad for performance
if (self.parser.framesetOK and
- any([char not in spaceCharacters
- for char in token["data"]])):
+ any(char not in spaceCharacters
+ for char in token["data"])):
self.parser.framesetOK = False
def processSpaceCharactersNonPre(self, token):
@@ -1850,7 +1850,7 @@ def __init__(self, *args, **kwargs):
def flushCharacters(self):
data = "".join([item["data"] for item in self.characterTokens])
- if any([item not in spaceCharacters for item in data]):
+ if any(item not in spaceCharacters for item in data):
token = {"type": tokenTypes["Characters"], "data": data}
self.parser.phases["inTable"].insertText(token)
elif data:
diff --git a/html5lib/serializer.py b/html5lib/serializer.py
index c66df683..a171ac1c 100644
--- a/html5lib/serializer.py
+++ b/html5lib/serializer.py
@@ -222,14 +222,14 @@ def __init__(self, **kwargs):
self.strict = False
def encode(self, string):
- assert(isinstance(string, text_type))
+ assert isinstance(string, text_type)
if self.encoding:
return string.encode(self.encoding, "htmlentityreplace")
else:
return string
def encodeStrict(self, string):
- assert(isinstance(string, text_type))
+ assert isinstance(string, text_type)
if self.encoding:
return string.encode(self.encoding, "strict")
else:
diff --git a/html5lib/tests/support.py b/html5lib/tests/support.py
index 9cd5afbe..1bd0ccc1 100644
--- a/html5lib/tests/support.py
+++ b/html5lib/tests/support.py
@@ -8,7 +8,7 @@
import glob
import xml.sax.handler
-base_path = os.path.split(__file__)[0]
+base_path = os.path.dirname(__file__)
test_dir = os.path.join(base_path, 'testdata')
sys.path.insert(0, os.path.abspath(os.path.join(base_path,
diff --git a/html5lib/tests/test_sanitizer.py b/html5lib/tests/test_sanitizer.py
index f3faeb80..6ad43a3a 100644
--- a/html5lib/tests/test_sanitizer.py
+++ b/html5lib/tests/test_sanitizer.py
@@ -1,9 +1,14 @@
from __future__ import absolute_import, division, unicode_literals
+import warnings
+
import pytest
from html5lib import constants, parseFragment, serialize
-from html5lib.filters import sanitizer
+
+with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ from html5lib.filters import sanitizer
def sanitize_html(stream):
diff --git a/html5lib/tests/test_serializer.py b/html5lib/tests/test_serializer.py
index bce62459..a2be0be5 100644
--- a/html5lib/tests/test_serializer.py
+++ b/html5lib/tests/test_serializer.py
@@ -74,7 +74,7 @@ def _convertAttrib(self, attribs):
attrs = {}
for attrib in attribs:
name = (attrib["namespace"], attrib["name"])
- assert(name not in attrs)
+ assert name not in attrs
attrs[name] = attrib["value"]
return attrs
diff --git a/html5lib/tests/tokenizertotree.py b/html5lib/tests/tokenizertotree.py
index 8528e876..42463f32 100644
--- a/html5lib/tests/tokenizertotree.py
+++ b/html5lib/tests/tokenizertotree.py
@@ -29,7 +29,7 @@ def run_file(filename, out_path):
except ValueError:
sys.stderr.write("Failed to load %s\n" % filename)
return
- name = os.path.splitext(os.path.split(filename)[1])[0]
+ name = os.path.splitext(os.path.basename(filename))[0]
output_file = open(os.path.join(out_path, "tokenizer_%s.dat" % name), "w")
if 'tests' in tests_data:
diff --git a/html5lib/treebuilders/etree.py b/html5lib/treebuilders/etree.py
index 086bed4e..0b745081 100644
--- a/html5lib/treebuilders/etree.py
+++ b/html5lib/treebuilders/etree.py
@@ -108,7 +108,7 @@ def removeChild(self, node):
node.parent = None
def insertText(self, data, insertBefore=None):
- if not(len(self._element)):
+ if not len(self._element):
if not self._element.text:
self._element.text = ""
self._element.text += data
@@ -201,7 +201,7 @@ def testSerializer(element):
rv = []
def serializeElement(element, indent=0):
- if not(hasattr(element, "tag")):
+ if not hasattr(element, "tag"):
element = element.getroot()
if element.tag == "":
if element.get("publicId") or element.get("systemId"):
diff --git a/html5lib/treewalkers/etree.py b/html5lib/treewalkers/etree.py
index 44653372..411a1d45 100644
--- a/html5lib/treewalkers/etree.py
+++ b/html5lib/treewalkers/etree.py
@@ -37,7 +37,7 @@ def getNodeDetails(self, node):
else:
node = elt
- if not(hasattr(node, "tag")):
+ if not hasattr(node, "tag"):
node = node.getroot()
if node.tag in ("DOCUMENT_ROOT", "DOCUMENT_FRAGMENT"):
diff --git a/pytest.ini b/pytest.ini
index 8824977a..1f620d98 100644
--- a/pytest.ini
+++ b/pytest.ini
@@ -1,6 +1,6 @@
[pytest]
# Output fails, errors, xpass, and warnings; ignore doctest; make warnings errors
-addopts = -rfEXw -p no:doctest --strict
+addopts = -rfEXw -p no:doctest --strict-markers
# Make xpass results be considered fail
xfail_strict = true
diff --git a/requirements-test.txt b/requirements-test.txt
index 57f8f617..8c0ca7c7 100644
--- a/requirements-test.txt
+++ b/requirements-test.txt
@@ -1,7 +1,7 @@
-r requirements.txt
tox>=3.15.1,<4
-flake8>=3.8.1,<3.9
+flake8>=3.8.1,<6
pytest>=4.6.10,<5 ; python_version < '3'
pytest>=5.4.2,<7 ; python_version >= '3'
coverage>=5.1,<6
diff --git a/setup.py b/setup.py
index f84c1284..b4c11811 100644
--- a/setup.py
+++ b/setup.py
@@ -70,6 +70,9 @@ def default_environment():
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
+ 'Programming Language :: Python :: 3.9',
+ 'Programming Language :: Python :: 3.10',
+ 'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
'Topic :: Software Development :: Libraries :: Python Modules',
diff --git a/tox.ini b/tox.ini
index 16b8cf41..42790f48 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,5 +1,5 @@
[tox]
-envlist = py{27,35,36,37,38,py,py3}-{base,six19,optional}
+envlist = py{27,35,36,37,38,39,310,311,py,py3}-{base,six19,optional}
[testenv]
deps =
@@ -12,7 +12,7 @@ passenv =
COVERAGE_RUN_OPTIONS
commands =
six19: pip install six==1.9
- {env:PYTEST_COMMAND:{envbindir}/py.test} {posargs}
+ {env:PYTEST_COMMAND:{envbindir}/pytest} {posargs}
flake8 {toxinidir}
[testenv:doc]