Skip to content
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
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ authors = [
maintainers = [
{name = "Andreas Stefl", email="stefl.andreas@gmail.com"},
]
requires-python = ">=3.7"
requires-python = ">=3.10"
readme = "README.md"
license = {file = "LICENSE.txt"}
dependencies = [
Expand Down
13 changes: 10 additions & 3 deletions src/htmlcmp/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@ def compare_html(a: Path, b: Path, browser=None, diff_output: Path = None) -> bo
raise FileNotFoundError("Both arguments must be files")

if browser is None:
browser = get_browser()
browser = get_browser("firefox")
diff, (image_a, image_b) = html_render_diff(a, b, browser=browser)
result = True if diff.getbbox() is None else False
result = diff.getbbox() is None
if diff_output is not None and not result:
diff_output.mkdir(parents=True, exist_ok=True)
image_a.save(diff_output / "a.png")
Expand All @@ -64,12 +64,19 @@ def compare_files(a: Path, b: Path, **kwargs) -> bool:
if not a.is_file() or not b.is_file():
raise FileNotFoundError("Both arguments must be files")

if filecmp.cmp(a, b):
if filecmp.cmp(a, b, shallow=False):
return True
if a.suffix == ".json":
return compare_json(a, b)
if a.suffix == ".html":
if kwargs.get("browser") is None:
# No browser available (e.g. --driver none): the files already
# differ at the byte level and we cannot render to check for visual
# equality, so report them as different rather than spinning up a
# browser here.
return False
return compare_html(a, b, **kwargs)
return False


def comparable_file(path: Path) -> bool:
Expand Down
22 changes: 16 additions & 6 deletions src/htmlcmp/compare_output_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ class Config:
observer = None
comparator = None
browser = None
# Serializes access to the single shared ``browser`` above: Flask serves
# requests from a thread pool and Selenium drivers are not thread-safe, so
# concurrent /image_diff requests would otherwise interleave on one driver.
browser_lock = threading.Lock()
thread_local = threading.local()
log_file: Path = None

Expand Down Expand Up @@ -722,11 +726,12 @@ def image_diff(path: str):
if not (Config.path_a / path).is_file() or not (Config.path_b / path).is_file():
return "Image diff not available: file missing on one side", 404

diff, _ = html_render_diff(
Config.path_a / path,
Config.path_b / path,
Config.browser,
)
with Config.browser_lock:
diff, _ = html_render_diff(
Config.path_a / path,
Config.path_b / path,
Config.browser,
)
tmp = io.BytesIO()
diff.save(tmp, "JPEG", quality=70)
tmp.seek(0)
Expand Down Expand Up @@ -786,6 +791,11 @@ def main():
parser.add_argument("--driver", choices=["chrome", "firefox"])
parser.add_argument("--max-workers", type=int, default=1)
parser.add_argument("--compare", action="store_true")
parser.add_argument(
"--host",
default="0.0.0.0",
help="Host/interface to bind the server to (default: 0.0.0.0)",
)
parser.add_argument("--port", type=int, default=5000)
parser.add_argument(
"-v",
Expand Down Expand Up @@ -820,7 +830,7 @@ def main():
Config.observer = Observer()
Config.observer.start()

app.run(host="0.0.0.0", port=args.port)
app.run(host=args.host, port=args.port)

if args.compare:
Config.observer.stop()
Expand Down
4 changes: 2 additions & 2 deletions src/htmlcmp/html_render_diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,8 @@ def main():
parser.add_argument("a", type=Path, help="Path to the first HTML file")
parser.add_argument("b", type=Path, help="Path to the second HTML file")
parser.add_argument("--driver", choices=["chrome", "firefox"], default="firefox")
parser.add_argument("--max-width", default=1000)
parser.add_argument("--max-height", default=10000)
parser.add_argument("--max-width", type=int, default=1000)
parser.add_argument("--max-height", type=int, default=10000)
args = parser.parse_args()

browser = get_browser(args.driver, args.max_width, args.max_height)
Expand Down
16 changes: 8 additions & 8 deletions src/htmlcmp/tidy_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,12 @@ def tidy_dir(
"error": [],
}

items = [p for p in path.iterdir()]
files = sorted([path for path in items if path.is_file() and tidyable_file(path)])
dirs = sorted([path for path in items if path.is_dir()])
items = list(path.iterdir())
files = sorted(p for p in items if p.is_file() and tidyable_file(p))
dirs = sorted(p for p in items if p.is_dir())

for filename in [path.name for path in files]:
filepath = path / filename
for filepath in files:
filename = filepath.name
tidy = tidy_file(filepath, html_tidy_config=html_tidy_config, verbose=verbose)
if tidy == 0:
print(f"{prefix_file}{bcolors.OKGREEN}{filename} ✓{bcolors.ENDC}")
Expand All @@ -128,10 +128,10 @@ def tidy_dir(
print(f"{prefix_file}{bcolors.FAIL}{filename} ✘{bcolors.ENDC}")
result["error"].append(filepath)

for dirname in [path.name for path in dirs]:
print(prefix + "├── " + dirname)
for dirpath in dirs:
print(prefix + "├── " + dirpath.name)
subresult = tidy_dir(
path / dirname,
dirpath,
level=level + 1,
prefix=prefix + "│ ",
html_tidy_config=html_tidy_config,
Expand Down
Loading