Skip to content

Drop support for legacy Python 2.7 #230

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Sep 9, 2019
Merged
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
17 changes: 0 additions & 17 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,6 @@ jobs:
directories:
- $HOME/.cache/pre-commit

-
python: 2.7
env: TOXENV=py27

-
python: 2.7
env: TOXENV=py27-ansi2html

-
python: 3.6
env: TOXENV=py36

Expand All @@ -45,14 +36,6 @@ jobs:
sudo: required
env: TOXENV=py37-ansi2html

-
python: pypy
env: TOXENV=pypy

-
python: pypy
env: TOXENV=pypy-ansi2html

-
python: pypy3
env: TOXENV=pypy3
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Requirements

You will need the following prerequisites in order to use pytest-html:

- Python 2.7, 3.6, PyPy, or PyPy3
- Python 3.6+ or PyPy3

Installation
------------
Expand Down
6 changes: 1 addition & 5 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,7 @@ environment:
- TOXENV: py36-pytest29
PYTHON_HOME: C:\Python36
- TOXENV: flake8
PYTHON_HOME: C:\Python27
- TOXENV: py27-pytest30
PYTHON_HOME: C:\Python27
- TOXENV: py27-pytest29
PYTHON_HOME: C:\Python27
PYTHON_HOME: C:\Python37
install:
- '%PYTHON_HOME%\Scripts\pip --version'
- '%PYTHON_HOME%\Scripts\pip install tox'
Expand Down
77 changes: 27 additions & 50 deletions pytest_html/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

from __future__ import absolute_import

from base64 import b64encode, b64decode
from collections import OrderedDict
from os.path import isfile
import datetime
import json
import os
import pkg_resources
import sys
import time
import bisect
import warnings
import re

from html import escape

try:
from ansi2html import Ansi2HTMLConverter, style

Expand All @@ -30,16 +29,6 @@
from . import extras
from . import __version__, __pypi_url__

PY3 = sys.version_info[0] == 3

# Python 2.X and 3.X compatibility
if PY3:
basestring = str
from html import escape
else:
from codecs import open
from cgi import escape


def pytest_addhooks(pluginmanager):
from . import hooks
Expand Down Expand Up @@ -95,10 +84,10 @@ def pytest_unconfigure(config):

def data_uri(content, mime_type="text/plain", charset="utf-8"):
data = b64encode(content.encode(charset)).decode("ascii")
return "data:{0};charset={1};base64,{2}".format(mime_type, charset, data)
return f"data:{mime_type};charset={charset};base64,{data}"


class HTMLReport(object):
class HTMLReport:
def __init__(self, logfile, config):
logfile = os.path.expanduser(os.path.expandvars(logfile))
self.logfile = os.path.abspath(logfile)
Expand Down Expand Up @@ -136,7 +125,7 @@ def __init__(self, outcome, report, logfile, config):
cells = [
html.td(self.outcome, class_="col-result"),
html.td(self.test_id, class_="col-name"),
html.td("{0:.2f}".format(self.time), class_="col-duration"),
html.td(f"{self.time:.2f}", class_="col-duration"),
html.td(self.links_html, class_="col-links"),
]

Expand Down Expand Up @@ -181,7 +170,7 @@ def create_asset(
if not os.path.exists(os.path.dirname(asset_path)):
os.makedirs(os.path.dirname(asset_path))

relative_path = "{0}/{1}".format("assets", asset_file_name)
relative_path = f"assets/{asset_file_name}"

kwargs = {"encoding": "utf-8"} if "b" not in mode else {}
with open(asset_path, mode, **kwargs) as f:
Expand Down Expand Up @@ -209,13 +198,10 @@ def append_extra_html(self, extra, extra_index, test_index):
)
html_div = html.a(html.img(src=content), href=content)
elif self.self_contained:
src = "data:{0};base64,{1}".format(extra.get("mime_type"), content)
src = "data:{};base64,{}".format(extra.get("mime_type"), content)
html_div = html.img(src=src)
else:
if PY3:
content = content.encode("utf-8")

content = b64decode(content)
content = b64decode(content.encode("utf-8"))
href = src = self.create_asset(
content, extra_index, test_index, extra.get("extension"), "wb"
)
Expand Down Expand Up @@ -276,7 +262,7 @@ def append_log_html(self, report, additional_html):

for section in report.sections:
header, content = map(escape, section)
log.append(" {0} ".format(header).center(80, "-"))
log.append(f" {header:-^80} ")
log.append(html.br())
if ANSI:
converter = Ansi2HTMLConverter(inline=False, escaped=False)
Expand All @@ -296,7 +282,7 @@ def _appendrow(self, outcome, report):
self.results.insert(index, result)
tbody = html.tbody(
result.row_table,
class_="{0} results-table-row".format(result.outcome.lower()),
class_="{} results-table-row".format(result.outcome.lower()),
)
if result.row_extra is not None:
tbody.append(result.row_extra)
Expand Down Expand Up @@ -345,9 +331,7 @@ def _generate_report(self, session):

self.style_css = pkg_resources.resource_string(
__name__, os.path.join("resources", "style.css")
)
if PY3:
self.style_css = self.style_css.decode("utf-8")
).decode("utf-8")

if ANSI:
ansi_css = [
Expand All @@ -362,12 +346,12 @@ def _generate_report(self, session):
for path in self.config.getoption("css"):
self.style_css += "\n/******************************"
self.style_css += "\n * CUSTOM CSS"
self.style_css += "\n * {}".format(path)
self.style_css += f"\n * {path}"
self.style_css += "\n ******************************/\n\n"
with open(path, "r") as f:
self.style_css += f.read()

css_href = "{0}/{1}".format("assets", "style.css")
css_href = "assets/style.css"
html_css = html.link(href=css_href, rel="stylesheet", type="text/css")
if self.self_contained:
html_css = html.style(raw(self.style_css))
Expand Down Expand Up @@ -401,12 +385,12 @@ def generate_checkbox(self):
name="filter_checkbox",
class_="filter",
hidden="true",
**checkbox_kwargs
**checkbox_kwargs,
)

def generate_summary_item(self):
self.summary_item = html.span(
"{0} {1}".format(self.total, self.label), class_=self.class_html
f"{self.total} {self.label}", class_=self.class_html
)

outcomes = [
Expand All @@ -422,9 +406,7 @@ def generate_summary_item(self):
outcomes.append(Outcome("rerun", self.rerun))

summary = [
html.p(
"{0} tests ran in {1:.2f} seconds. ".format(numtests, suite_time_delta)
),
html.p(f"{numtests} tests ran in {suite_time_delta:.2f} seconds. "),
html.p(
"(Un)check the boxes to filter the results.",
class_="filter",
Expand Down Expand Up @@ -472,19 +454,17 @@ def generate_summary_item(self):

main_js = pkg_resources.resource_string(
__name__, os.path.join("resources", "main.js")
)
if PY3:
main_js = main_js.decode("utf-8")
).decode("utf-8")

body = html.body(
html.script(raw(main_js)),
html.h1(os.path.basename(self.logfile)),
html.p(
"Report generated on {0} at {1} by ".format(
"Report generated on {} at {} by ".format(
generated.strftime("%d-%b-%Y"), generated.strftime("%H:%M:%S")
),
html.a("pytest-html", href=__pypi_url__),
" v{0}".format(__version__),
f" v{__version__}",
),
onLoad="init()",
)
Expand All @@ -501,12 +481,11 @@ def generate_summary_item(self):

doc = html.html(head, body)

unicode_doc = u"<!DOCTYPE html>\n{0}".format(doc.unicode(indent=2))
if PY3:
# Fix encoding issues, e.g. with surrogates
unicode_doc = unicode_doc.encode("utf-8", errors="xmlcharrefreplace")
unicode_doc = unicode_doc.decode("utf-8")
return unicode_doc
unicode_doc = "<!DOCTYPE html>\n{}".format(doc.unicode(indent=2))

# Fix encoding issues, e.g. with surrogates
unicode_doc = unicode_doc.encode("utf-8", errors="xmlcharrefreplace")
return unicode_doc.decode("utf-8")

def _generate_environment(self, config):
if not hasattr(config, "_metadata") or config._metadata is None:
Expand All @@ -522,10 +501,10 @@ def _generate_environment(self, config):

for key in keys:
value = metadata[key]
if isinstance(value, basestring) and value.startswith("http"):
if isinstance(value, str) and value.startswith("http"):
value = html.a(value, href=value, target="_blank")
elif isinstance(value, (list, tuple, set)):
value = ", ".join((str(i) for i in value))
value = ", ".join(str(i) for i in value)
rows.append(html.tr(html.td(key), html.td(value)))

environment.append(html.table(rows, id="environment"))
Expand Down Expand Up @@ -569,6 +548,4 @@ def pytest_sessionfinish(self, session):
self._save_report(report_content)

def pytest_terminal_summary(self, terminalreporter):
terminalreporter.write_sep(
"-", "generated html file: file://{0}".format(self.logfile)
)
terminalreporter.write_sep("-", f"generated html file: file://{self.logfile}")
6 changes: 4 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
package_data={"pytest_html": ["resources/*"]},
entry_points={"pytest11": ["html = pytest_html.plugin"]},
setup_requires=["setuptools_scm"],
install_requires=["pytest>=3.0", "pytest-metadata"],
install_requires=["pytest>=5.0", "pytest-metadata"],
license="Mozilla Public License 2.0 (MPL 2.0)",
keywords="py.test pytest html report",
python_requires=">=3.6",
classifiers=[
"Development Status :: 5 - Production/Stable",
"Framework :: Pytest",
Expand All @@ -27,8 +28,9 @@
"Topic :: Software Development :: Testing",
"Topic :: Utilities",
"Programming Language :: Python",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3 :: Only",
],
)
Loading