dir-content-diff 1.11.0__tar.gz → 1.12.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.copier-answers.yml +1 -1
- dir_content_diff-1.12.1/.copyright.tmpl +6 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/workflows/run-tox.yml +16 -7
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.pre-commit-config.yaml +16 -4
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/CHANGELOG.md +29 -0
- {dir_content_diff-1.11.0/dir_content_diff.egg-info → dir_content_diff-1.12.1}/PKG-INFO +15 -9
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff/__init__.py +51 -16
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff/base_comparators.py +130 -8
- dir_content_diff-1.12.1/dir_content_diff/cli/__init__.py +188 -0
- dir_content_diff-1.12.1/dir_content_diff/comparators/__init__.py +10 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff/comparators/dependencies.json +1 -1
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff/comparators/morphio.py +9 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff/comparators/pandas.py +9 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff/comparators/voxcell.py +27 -4
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff/pytest_plugin.py +9 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff/util.py +48 -13
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1/dir_content_diff.egg-info}/PKG-INFO +15 -9
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff.egg-info/SOURCES.txt +3 -1
- dir_content_diff-1.12.1/dir_content_diff.egg-info/entry_points.txt +5 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff.egg-info/requires.txt +8 -4
- dir_content_diff-1.12.1/docs/source/changelog.rst +2 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/docs/source/conf.py +22 -3
- dir_content_diff-1.12.1/docs/source/contributing.rst +2 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/docs/source/index.rst +2 -1
- dir_content_diff-1.12.1/pyproject.toml +94 -0
- dir_content_diff-1.12.1/setup.py +49 -0
- dir_content_diff-1.12.1/tests/__init__.py +10 -0
- dir_content_diff-1.12.1/tests/comparators/__init__.py +10 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/comparators/test_morphio.py +10 -1
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/comparators/test_pandas.py +53 -10
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/comparators/test_voxcell.py +18 -3
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/conftest.py +17 -2
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/generate_test_files.py +9 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/test_base.py +197 -33
- dir_content_diff-1.12.1/tests/test_cli.py +276 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/test_missing_deps.py +9 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/test_pytest_plugin.py +9 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/test_util.py +9 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tests/test_version.py +9 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/tox.ini +9 -1
- dir_content_diff-1.11.0/.flake8 +0 -7
- dir_content_diff-1.11.0/dir_content_diff/comparators/__init__.py +0 -1
- dir_content_diff-1.11.0/dir_content_diff.egg-info/entry_points.txt +0 -2
- dir_content_diff-1.11.0/docs/source/changelog.rst +0 -1
- dir_content_diff-1.11.0/docs/source/contributing.rst +0 -1
- dir_content_diff-1.11.0/pyproject.toml +0 -38
- dir_content_diff-1.11.0/setup.py +0 -81
- dir_content_diff-1.11.0/tests/__init__.py +0 -1
- dir_content_diff-1.11.0/tests/comparators/__init__.py +0 -1
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.auto-changelog +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.auto-changelog-template.hbs +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.codespellignorelines +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.codespellrc +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.coveragerc +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.coveragerc_min_versions +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.gitattributes +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/ISSUE_TEMPLATE/bug_report.yaml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/ISSUE_TEMPLATE/feature_request.yaml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/ISSUE_TEMPLATE/how_to_use.yaml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/dependabot.yml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/pull_request_template.md +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/workflows/commitlint.yml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.github/workflows/publish-sdist.yml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.gitignore +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.gitreview +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.pylintrc +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/.readthedocs.yml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/AUTHORS.md +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/CONTRIBUTING.md +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/LICENSE.txt +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/MANIFEST.in +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/README.md +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/codecov.yml +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/commitlint.config.js +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff.egg-info/dependency_links.txt +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/dir_content_diff.egg-info/top_level.txt +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/docs/Makefile +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/docs/source/.gitignore +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/docs/source/api_ref.rst +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/package.json +0 -0
- {dir_content_diff-1.11.0 → dir_content_diff-1.12.1}/setup.cfg +0 -0
|
@@ -21,7 +21,7 @@ setup_codeql: false
|
|
|
21
21
|
ssh_url: git@github.com:BlueBrain/dir-content-diff.git
|
|
22
22
|
team_name: ''
|
|
23
23
|
tracker_url: https://github.com/BlueBrain/dir-content-diff/issues
|
|
24
|
-
use_pyproject_toml:
|
|
24
|
+
use_pyproject_toml: true
|
|
25
25
|
version: 1.1.0
|
|
26
26
|
|
|
27
27
|
# End of Copier answers
|
|
@@ -6,6 +6,8 @@ on:
|
|
|
6
6
|
branches:
|
|
7
7
|
- main
|
|
8
8
|
workflow_dispatch:
|
|
9
|
+
schedule:
|
|
10
|
+
- cron: "0 2 15 1,7 *"
|
|
9
11
|
|
|
10
12
|
jobs:
|
|
11
13
|
build:
|
|
@@ -30,12 +32,9 @@ jobs:
|
|
|
30
32
|
- name: Get current month
|
|
31
33
|
id: date
|
|
32
34
|
run: echo "date=$(date +'%Y-%m')" >> $GITHUB_OUTPUT
|
|
33
|
-
- name:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
packages: poppler-utils imagemagick
|
|
37
|
-
version: 1.0
|
|
38
|
-
execute_install_scripts: true
|
|
35
|
+
- name: Install APT Packages
|
|
36
|
+
run: |
|
|
37
|
+
sudo apt-get install -y poppler-utils imagemagick
|
|
39
38
|
- name: Cache tox and precommit environments
|
|
40
39
|
uses: actions/cache@v4
|
|
41
40
|
with:
|
|
@@ -64,13 +63,23 @@ jobs:
|
|
|
64
63
|
with:
|
|
65
64
|
report_paths: 'reports/pytest-*.xml'
|
|
66
65
|
- name: Upload to codecov
|
|
67
|
-
uses: codecov/codecov-action@
|
|
66
|
+
uses: codecov/codecov-action@v5
|
|
68
67
|
with:
|
|
69
68
|
fail_ci_if_error: false
|
|
70
69
|
directory: ./reports
|
|
71
70
|
flags: pytest
|
|
72
71
|
name: "dir-content-diff-py${{ matrix.python-version }}-${{ matrix.min_versions }}"
|
|
73
72
|
token: ${{ secrets.CODECOV_TOKEN }}
|
|
73
|
+
- name: Upload to codecov results
|
|
74
|
+
uses: codecov/test-results-action@v1
|
|
75
|
+
with:
|
|
76
|
+
fail_ci_if_error: false
|
|
77
|
+
flags: pytest
|
|
78
|
+
directory: ./reports
|
|
79
|
+
name: "dir-content-diff-py${{ matrix.python-version }}-${{ matrix.min_versions }}-test-results"
|
|
80
|
+
token: ${{ secrets.CODECOV_TOKEN }}
|
|
81
|
+
env:
|
|
82
|
+
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
|
74
83
|
- name: Upload test artifacts
|
|
75
84
|
uses: actions/upload-artifact@v4
|
|
76
85
|
if: always()
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.7.0
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: ["--fix", "--exit-non-zero-on-fix"]
|
|
7
|
+
- id: ruff-format
|
|
2
8
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
9
|
rev: v5.0.0
|
|
4
10
|
hooks:
|
|
@@ -21,10 +27,6 @@ repos:
|
|
|
21
27
|
rev: 5.13.2
|
|
22
28
|
hooks:
|
|
23
29
|
- id: isort
|
|
24
|
-
- repo: https://github.com/psf/black
|
|
25
|
-
rev: 24.10.0
|
|
26
|
-
hooks:
|
|
27
|
-
- id: black
|
|
28
30
|
- repo: https://github.com/codespell-project/codespell
|
|
29
31
|
rev: v2.3.0
|
|
30
32
|
hooks:
|
|
@@ -39,3 +41,13 @@ repos:
|
|
|
39
41
|
rev: 7.1.1
|
|
40
42
|
hooks:
|
|
41
43
|
- id: flake8
|
|
44
|
+
additional_dependencies: ['flake8-pyproject']
|
|
45
|
+
- repo: https://github.com/arkinmodi/add-license-header
|
|
46
|
+
rev: v2.2.0
|
|
47
|
+
hooks:
|
|
48
|
+
- id: add-license-header
|
|
49
|
+
args:
|
|
50
|
+
- --unmanaged
|
|
51
|
+
- --license-file
|
|
52
|
+
- .copyright.tmpl
|
|
53
|
+
files: \.py$
|
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.12.1](https://github.com/BlueBrain/dir-content-diff/compare/1.12.0..1.12.1)
|
|
4
|
+
|
|
5
|
+
> 3 July 2025
|
|
6
|
+
|
|
7
|
+
### Fixes
|
|
8
|
+
|
|
9
|
+
- Properly update the verbosity in PDF comparator (Adrien Berchet - [#75](https://github.com/BlueBrain/dir-content-diff/pull/75))
|
|
10
|
+
|
|
11
|
+
### CI Improvements
|
|
12
|
+
|
|
13
|
+
- Schedule CI every 6 months (Adrien Berchet - [#76](https://github.com/BlueBrain/dir-content-diff/pull/76))
|
|
14
|
+
|
|
15
|
+
## [1.12.0](https://github.com/BlueBrain/dir-content-diff/compare/1.11.0..1.12.0)
|
|
16
|
+
|
|
17
|
+
> 18 November 2024
|
|
18
|
+
|
|
19
|
+
### New Features
|
|
20
|
+
|
|
21
|
+
- Add CLI (Adrien Berchet - [#70](https://github.com/BlueBrain/dir-content-diff/pull/70))
|
|
22
|
+
- Intercept 'tempfile' argument of the PdfComparator to improve it (Adrien Berchet - [#69](https://github.com/BlueBrain/dir-content-diff/pull/69))
|
|
23
|
+
|
|
24
|
+
### Chores And Housekeeping
|
|
25
|
+
|
|
26
|
+
- Add license headers, use pyproject.toml file and migrate docs to MyST parser (Adrien Berchet - [#68](https://github.com/BlueBrain/dir-content-diff/pull/68))
|
|
27
|
+
|
|
28
|
+
### CI Improvements
|
|
29
|
+
|
|
30
|
+
- Push test results to Codecov (Adrien Berchet - [#73](https://github.com/BlueBrain/dir-content-diff/pull/73))
|
|
31
|
+
|
|
3
32
|
## [1.11.0](https://github.com/BlueBrain/dir-content-diff/compare/1.10.0..1.11.0)
|
|
4
33
|
|
|
5
34
|
> 6 November 2024
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: dir-content-diff
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.12.1
|
|
4
4
|
Summary: Simple tool to compare directory contents.
|
|
5
|
-
Home-page: https://dir-content-diff.readthedocs.io
|
|
6
5
|
Author: Blue Brain Project, EPFL
|
|
7
6
|
License: Apache License 2.0
|
|
7
|
+
Project-URL: Homepage, https://dir-content-diff.readthedocs.io
|
|
8
|
+
Project-URL: Repository, https://github.com/BlueBrain/dir-content-diff
|
|
8
9
|
Project-URL: Tracker, https://github.com/BlueBrain/dir-content-diff/issues
|
|
9
|
-
Project-URL: Source, https://github.com/BlueBrain/dir-content-diff
|
|
10
10
|
Classifier: Development Status :: 5 - Production/Stable
|
|
11
11
|
Classifier: Intended Audience :: Developers
|
|
12
12
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
@@ -16,15 +16,17 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
-
Classifier: Topic ::
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
20
|
Requires-Python: >=3.9
|
|
21
21
|
Description-Content-Type: text/markdown
|
|
22
22
|
License-File: LICENSE.txt
|
|
23
23
|
License-File: AUTHORS.md
|
|
24
|
+
Requires-Dist: click>=8
|
|
24
25
|
Requires-Dist: dictdiffer>=0.8
|
|
25
26
|
Requires-Dist: dicttoxml>=1.7.12
|
|
26
27
|
Requires-Dist: diff_pdf_visually>=1.7
|
|
27
28
|
Requires-Dist: jsonpath-ng>=1.5
|
|
29
|
+
Requires-Dist: packaging>=20
|
|
28
30
|
Requires-Dist: PyYaml>=6
|
|
29
31
|
Provides-Extra: all-comparators
|
|
30
32
|
Requires-Dist: pandas>=1.4; extra == "all-comparators"
|
|
@@ -33,19 +35,20 @@ Requires-Dist: tables>=3.7; extra == "all-comparators"
|
|
|
33
35
|
Requires-Dist: morphio>=3.3.6; extra == "all-comparators"
|
|
34
36
|
Requires-Dist: morph_tool>=2.9; extra == "all-comparators"
|
|
35
37
|
Requires-Dist: voxcell>=3.1.1; extra == "all-comparators"
|
|
38
|
+
Requires-Dist: pynrrd<1.1,>=0.4; extra == "all-comparators"
|
|
36
39
|
Provides-Extra: docs
|
|
37
|
-
Requires-Dist:
|
|
38
|
-
Requires-Dist: m2r2; extra == "docs"
|
|
40
|
+
Requires-Dist: myst_parser; extra == "docs"
|
|
39
41
|
Requires-Dist: sphinx; extra == "docs"
|
|
40
42
|
Requires-Dist: sphinx-bluebrain-theme; extra == "docs"
|
|
41
43
|
Provides-Extra: test
|
|
42
|
-
Requires-Dist: coverage>=7.2; extra == "test"
|
|
43
44
|
Requires-Dist: dicttoxml>=1.7.16; extra == "test"
|
|
44
45
|
Requires-Dist: matplotlib>=3.4; extra == "test"
|
|
45
46
|
Requires-Dist: rst2pdf>=0.99; extra == "test"
|
|
46
|
-
Requires-Dist: packaging>=20; extra == "test"
|
|
47
47
|
Requires-Dist: pandas>=1.4; extra == "test"
|
|
48
48
|
Requires-Dist: pytest>=6.2; extra == "test"
|
|
49
|
+
Requires-Dist: pytest-click>=1.1; extra == "test"
|
|
50
|
+
Requires-Dist: pytest-console-scripts>=1.4; extra == "test"
|
|
51
|
+
Requires-Dist: pytest-cov>=4.1; extra == "test"
|
|
49
52
|
Requires-Dist: pytest-html>=3.2; extra == "test"
|
|
50
53
|
Provides-Extra: pandas
|
|
51
54
|
Requires-Dist: pandas>=1.4; extra == "pandas"
|
|
@@ -56,6 +59,9 @@ Requires-Dist: morphio>=3.3.6; extra == "morphio"
|
|
|
56
59
|
Requires-Dist: morph_tool>=2.9; extra == "morphio"
|
|
57
60
|
Provides-Extra: voxcell
|
|
58
61
|
Requires-Dist: voxcell>=3.1.1; extra == "voxcell"
|
|
62
|
+
Requires-Dist: pynrrd<1.1,>=0.4; extra == "voxcell"
|
|
63
|
+
Dynamic: license-file
|
|
64
|
+
Dynamic: provides-extra
|
|
59
65
|
|
|
60
66
|
[](https://github.com/BlueBrain/dir-content-diff/releases)
|
|
61
67
|
[](https://github.com/BlueBrain/dir-content-diff/actions)
|
|
@@ -3,11 +3,21 @@
|
|
|
3
3
|
Simple tool to compare directory contents.
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
|
+
# LICENSE HEADER MANAGED BY add-license-header
|
|
7
|
+
# Copyright (c) 2023-2025 Blue Brain Project, EPFL.
|
|
8
|
+
#
|
|
9
|
+
# This file is part of dir-content-diff.
|
|
10
|
+
# See https://github.com/BlueBrain/dir-content-diff for further info.
|
|
11
|
+
#
|
|
12
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
13
|
+
# LICENSE HEADER MANAGED BY add-license-header
|
|
14
|
+
|
|
6
15
|
import copy
|
|
7
16
|
import importlib.metadata
|
|
8
17
|
import re
|
|
9
18
|
from pathlib import Path
|
|
10
19
|
|
|
20
|
+
from dir_content_diff.base_comparators import BaseComparator
|
|
11
21
|
from dir_content_diff.base_comparators import DefaultComparator
|
|
12
22
|
from dir_content_diff.base_comparators import IniComparator
|
|
13
23
|
from dir_content_diff.base_comparators import JsonComparator
|
|
@@ -20,7 +30,6 @@ from dir_content_diff.util import format_ext
|
|
|
20
30
|
|
|
21
31
|
__version__ = importlib.metadata.version("dir-content-diff")
|
|
22
32
|
|
|
23
|
-
|
|
24
33
|
_DEFAULT_COMPARATORS = {
|
|
25
34
|
None: DefaultComparator(),
|
|
26
35
|
".cfg": IniComparator(), # luigi config files
|
|
@@ -106,7 +115,9 @@ def unregister_comparator(ext, quiet=False):
|
|
|
106
115
|
return _COMPARATORS.pop(ext, None)
|
|
107
116
|
|
|
108
117
|
|
|
109
|
-
def compare_files(
|
|
118
|
+
def compare_files(
|
|
119
|
+
ref_file, comp_file, comparator, *args, return_raw_diffs=False, **kwargs
|
|
120
|
+
):
|
|
110
121
|
"""Compare 2 files and return the difference.
|
|
111
122
|
|
|
112
123
|
Args:
|
|
@@ -127,7 +138,9 @@ def compare_files(ref_file, comp_file, comparator, *args, return_raw_diffs=False
|
|
|
127
138
|
LOGGER.debug("Compare: %s and %s", ref_file, comp_file)
|
|
128
139
|
|
|
129
140
|
try:
|
|
130
|
-
return comparator(
|
|
141
|
+
return comparator(
|
|
142
|
+
ref_file, comp_file, *args, return_raw_diffs=return_raw_diffs, **kwargs
|
|
143
|
+
)
|
|
131
144
|
except Exception as exception: # pylint: disable=broad-except
|
|
132
145
|
load_kwargs = kwargs.pop("load_kwargs", None)
|
|
133
146
|
format_data_kwargs = kwargs.pop("format_data_kwargs", None)
|
|
@@ -139,7 +152,9 @@ def compare_files(ref_file, comp_file, comparator, *args, return_raw_diffs=False
|
|
|
139
152
|
try:
|
|
140
153
|
exception_args = "\n".join(str(i) for i in exception.args)
|
|
141
154
|
except Exception: # pylint: disable=broad-exception-caught
|
|
142
|
-
exception_args =
|
|
155
|
+
exception_args = (
|
|
156
|
+
"UNKNOWN ERROR: Could not get information from the exception"
|
|
157
|
+
)
|
|
143
158
|
exc_type = type(exception).__name__
|
|
144
159
|
return diff_msg_formatter(
|
|
145
160
|
ref_file,
|
|
@@ -209,9 +224,32 @@ def export_formatted_file(file, formatted_file, comparator, **kwargs):
|
|
|
209
224
|
),
|
|
210
225
|
)
|
|
211
226
|
else:
|
|
212
|
-
LOGGER.
|
|
213
|
-
"Skip formatting for '%s' because the comparator has no saving capability.",
|
|
227
|
+
LOGGER.debug(
|
|
228
|
+
"Skip formatting for '%s' because the comparator has no saving capability.",
|
|
229
|
+
file,
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def pick_comparator(comparator=None, suffix=None, comparators=None):
|
|
234
|
+
"""Pick a comparator based on its name or a file suffix."""
|
|
235
|
+
if isinstance(comparator, BaseComparator):
|
|
236
|
+
return comparator
|
|
237
|
+
if comparators is None:
|
|
238
|
+
comparators = get_comparators()
|
|
239
|
+
if comparator is not None:
|
|
240
|
+
for i in comparators.values(): # pragma: no branch
|
|
241
|
+
if i.__class__.__name__ == comparator:
|
|
242
|
+
return i
|
|
243
|
+
LOGGER.debug(
|
|
244
|
+
"Could not find the comparator named '%s' in the given comparators",
|
|
245
|
+
comparator,
|
|
214
246
|
)
|
|
247
|
+
if suffix is not None:
|
|
248
|
+
if suffix in comparators:
|
|
249
|
+
return comparators.get(suffix)
|
|
250
|
+
LOGGER.debug("Could not find the comparator for the '%s' suffix", suffix)
|
|
251
|
+
LOGGER.debug("Returning the default comparator")
|
|
252
|
+
return _COMPARATORS.get(None)
|
|
215
253
|
|
|
216
254
|
|
|
217
255
|
def compare_trees(
|
|
@@ -274,9 +312,6 @@ def compare_trees(
|
|
|
274
312
|
difference messages. If the directories are considered as equal, an empty ``dict`` is
|
|
275
313
|
returned.
|
|
276
314
|
"""
|
|
277
|
-
if comparators is None:
|
|
278
|
-
comparators = _COMPARATORS
|
|
279
|
-
|
|
280
315
|
ref_path = Path(ref_path)
|
|
281
316
|
comp_path = Path(comp_path)
|
|
282
317
|
formatted_data_path = comp_path.with_name(
|
|
@@ -316,12 +351,10 @@ def compare_trees(
|
|
|
316
351
|
break
|
|
317
352
|
if specific_file_args is None:
|
|
318
353
|
specific_file_args = {}
|
|
319
|
-
comparator =
|
|
320
|
-
"comparator",
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
_COMPARATORS.get(None),
|
|
324
|
-
),
|
|
354
|
+
comparator = pick_comparator(
|
|
355
|
+
comparator=specific_file_args.pop("comparator", None),
|
|
356
|
+
suffix=ref_file.suffix,
|
|
357
|
+
comparators=comparators,
|
|
325
358
|
)
|
|
326
359
|
comparator_args = specific_file_args.pop("args", [])
|
|
327
360
|
res = compare_files(
|
|
@@ -376,7 +409,9 @@ def assert_equal_trees(*args, export_formatted_files=False, **kwargs):
|
|
|
376
409
|
if export_formatted_files is True and assert_equal_trees._pytest_export_suffix:
|
|
377
410
|
export_formatted_files = assert_equal_trees._pytest_export_suffix
|
|
378
411
|
|
|
379
|
-
different_files = compare_trees(
|
|
412
|
+
different_files = compare_trees(
|
|
413
|
+
*args, export_formatted_files=export_formatted_files, **kwargs
|
|
414
|
+
)
|
|
380
415
|
|
|
381
416
|
# Sort the files according to their relative paths
|
|
382
417
|
sorted_items = sorted(different_files.items(), key=lambda x: x[0])
|
|
@@ -1,18 +1,29 @@
|
|
|
1
1
|
"""Module containing the base comparators."""
|
|
2
2
|
|
|
3
|
+
# LICENSE HEADER MANAGED BY add-license-header
|
|
4
|
+
# Copyright (c) 2023-2025 Blue Brain Project, EPFL.
|
|
5
|
+
#
|
|
6
|
+
# This file is part of dir-content-diff.
|
|
7
|
+
# See https://github.com/BlueBrain/dir-content-diff for further info.
|
|
8
|
+
#
|
|
9
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
10
|
+
# LICENSE HEADER MANAGED BY add-license-header
|
|
11
|
+
|
|
3
12
|
import configparser
|
|
4
13
|
import filecmp
|
|
5
14
|
import json
|
|
6
15
|
import re
|
|
7
16
|
from abc import ABC
|
|
8
17
|
from abc import abstractmethod
|
|
18
|
+
from pathlib import Path
|
|
9
19
|
from xml.etree import ElementTree
|
|
10
20
|
|
|
11
21
|
import dictdiffer
|
|
22
|
+
import diff_pdf_visually
|
|
12
23
|
import jsonpath_ng
|
|
13
24
|
import yaml
|
|
14
25
|
from dicttoxml import dicttoxml
|
|
15
|
-
from diff_pdf_visually import
|
|
26
|
+
from diff_pdf_visually import pdfdiff_pages
|
|
16
27
|
|
|
17
28
|
from dir_content_diff.util import diff_msg_formatter
|
|
18
29
|
|
|
@@ -222,7 +233,10 @@ class BaseComparator(ABC):
|
|
|
222
233
|
if hasattr(filtered_diffs, "items"):
|
|
223
234
|
formatted_diffs = self.concatenate(
|
|
224
235
|
self.sort(
|
|
225
|
-
[
|
|
236
|
+
[
|
|
237
|
+
self.format_diff(i, **format_diff_kwargs)
|
|
238
|
+
for i in filtered_diffs.items()
|
|
239
|
+
],
|
|
226
240
|
**sort_kwargs,
|
|
227
241
|
),
|
|
228
242
|
**concat_kwargs,
|
|
@@ -230,7 +244,10 @@ class BaseComparator(ABC):
|
|
|
230
244
|
else:
|
|
231
245
|
formatted_diffs = self.concatenate(
|
|
232
246
|
self.sort(
|
|
233
|
-
[
|
|
247
|
+
[
|
|
248
|
+
self.format_diff(i, **format_diff_kwargs)
|
|
249
|
+
for i in filtered_diffs
|
|
250
|
+
],
|
|
234
251
|
**sort_kwargs,
|
|
235
252
|
),
|
|
236
253
|
**concat_kwargs,
|
|
@@ -254,7 +271,10 @@ class BaseComparator(ABC):
|
|
|
254
271
|
|
|
255
272
|
def __eq__(self, other):
|
|
256
273
|
"""Compare 2 :class:`dir_content_diff.base_comparators.BaseComparator` instances."""
|
|
257
|
-
if
|
|
274
|
+
if (
|
|
275
|
+
type(self) is not type(other)
|
|
276
|
+
or self.__dict__.keys() != other.__dict__.keys()
|
|
277
|
+
):
|
|
258
278
|
return False
|
|
259
279
|
|
|
260
280
|
for k, v in self.__dict__.items():
|
|
@@ -363,7 +383,8 @@ class DictComparator(BaseComparator):
|
|
|
363
383
|
for i in path.find(data):
|
|
364
384
|
if isinstance(i.value, str):
|
|
365
385
|
i.full_path.update(
|
|
366
|
-
data,
|
|
386
|
+
data,
|
|
387
|
+
re.sub(pattern, new_value, i.value, count, flags),
|
|
367
388
|
)
|
|
368
389
|
return data
|
|
369
390
|
|
|
@@ -510,7 +531,13 @@ class XmlComparator(DictComparator):
|
|
|
510
531
|
def add_to_output(obj, child):
|
|
511
532
|
"""Add entry from :class:`xml.etree.ElementTree.Element` object into the given object."""
|
|
512
533
|
if isinstance(obj, dict):
|
|
513
|
-
obj.update(
|
|
534
|
+
obj.update(
|
|
535
|
+
{
|
|
536
|
+
child.tag: XmlComparator._cast_from_attribute(
|
|
537
|
+
child.text, child.attrib
|
|
538
|
+
)
|
|
539
|
+
}
|
|
540
|
+
)
|
|
514
541
|
for sub in child:
|
|
515
542
|
XmlComparator.add_to_output(obj[child.tag], sub)
|
|
516
543
|
elif isinstance(obj, list):
|
|
@@ -592,7 +619,8 @@ class PdfComparator(BaseComparator):
|
|
|
592
619
|
|
|
593
620
|
Keyword Args:
|
|
594
621
|
threshold (int): The threshold used to compare the images.
|
|
595
|
-
tempdir (pathlib.Path):
|
|
622
|
+
tempdir (pathlib.Path): Directory in which a new ``dir-diff`` directory will be created
|
|
623
|
+
to export the debug images.
|
|
596
624
|
dpi (int): The resolution used to convert the PDF files into images.
|
|
597
625
|
verbosity (int): The log verbosity.
|
|
598
626
|
max_report_pagenos (int): Only this number of the different pages will be logged (only
|
|
@@ -600,4 +628,98 @@ class PdfComparator(BaseComparator):
|
|
|
600
628
|
num_threads (int): If set to 2 (the default), the image conversion are processed in
|
|
601
629
|
parallel. If set to 1 it is processed sequentially.
|
|
602
630
|
"""
|
|
603
|
-
|
|
631
|
+
res = pdfdiff_pages(ref, comp, *args, **kwargs)
|
|
632
|
+
if not res:
|
|
633
|
+
return False
|
|
634
|
+
return res
|
|
635
|
+
|
|
636
|
+
def __call__(self, ref_file, comp_file, *args, **kwargs):
|
|
637
|
+
"""Process arguments before calling the diff method."""
|
|
638
|
+
tempdir = kwargs.pop("tempdir", None)
|
|
639
|
+
if tempdir is not None:
|
|
640
|
+
relative_parts = []
|
|
641
|
+
for i, j in zip(
|
|
642
|
+
ref_file.parts[::-1], comp_file.parts[::-1]
|
|
643
|
+
): # pragma: no branch
|
|
644
|
+
if i != j:
|
|
645
|
+
break
|
|
646
|
+
relative_parts.append(i)
|
|
647
|
+
if relative_parts and relative_parts[-1] == Path(tempdir).root:
|
|
648
|
+
relative_parts.pop()
|
|
649
|
+
if not relative_parts:
|
|
650
|
+
relative_parts.append(comp_file.name)
|
|
651
|
+
relative_parts.append("diff-pdf")
|
|
652
|
+
new_tempdir = Path(tempdir) / Path(*relative_parts[::-1])
|
|
653
|
+
|
|
654
|
+
# Deduplicate name if needed
|
|
655
|
+
last_part = str(relative_parts[-1])
|
|
656
|
+
num = 1
|
|
657
|
+
while True:
|
|
658
|
+
root = Path(tempdir) / relative_parts[-1]
|
|
659
|
+
if not root.exists():
|
|
660
|
+
new_tempdir.mkdir(parents=True, exist_ok=False)
|
|
661
|
+
break
|
|
662
|
+
relative_parts[-1] = last_part + f"_{num}"
|
|
663
|
+
new_tempdir = Path(tempdir) / Path(*relative_parts[::-1])
|
|
664
|
+
num += 1
|
|
665
|
+
|
|
666
|
+
kwargs["tempdir"] = new_tempdir
|
|
667
|
+
|
|
668
|
+
# Update default verbosity
|
|
669
|
+
current_default_verbosity = diff_pdf_visually.constants.DEFAULT_VERBOSITY
|
|
670
|
+
try:
|
|
671
|
+
if "verbosity" not in kwargs: # pragma: no branch
|
|
672
|
+
if (
|
|
673
|
+
diff_pdf_visually.diff.pdfdiff_pages.__defaults__[1] is None
|
|
674
|
+
): # pragma: no cover
|
|
675
|
+
diff_pdf_visually.constants.DEFAULT_VERBOSITY = 0
|
|
676
|
+
else:
|
|
677
|
+
kwargs["verbosity"] = 0 # pragma: no cover
|
|
678
|
+
return super().__call__(ref_file, comp_file, *args, **kwargs)
|
|
679
|
+
finally:
|
|
680
|
+
diff_pdf_visually.constants.DEFAULT_VERBOSITY = current_default_verbosity
|
|
681
|
+
|
|
682
|
+
def report(
|
|
683
|
+
self,
|
|
684
|
+
ref_file,
|
|
685
|
+
comp_file,
|
|
686
|
+
formatted_differences,
|
|
687
|
+
diff_args,
|
|
688
|
+
diff_kwargs,
|
|
689
|
+
load_kwargs=None,
|
|
690
|
+
format_data_kwargs=None,
|
|
691
|
+
filter_kwargs=None,
|
|
692
|
+
format_diff_kwargs=None,
|
|
693
|
+
sort_kwargs=None,
|
|
694
|
+
concat_kwargs=None,
|
|
695
|
+
**kwargs,
|
|
696
|
+
): # pylint: disable=too-many-arguments
|
|
697
|
+
"""Add specific information before calling the default method."""
|
|
698
|
+
if formatted_differences and isinstance(formatted_differences, str):
|
|
699
|
+
formatted_differences = (
|
|
700
|
+
"The following pages are the most different: "
|
|
701
|
+
+ formatted_differences.replace("\n", ", ")
|
|
702
|
+
)
|
|
703
|
+
if "tempdir" in diff_kwargs:
|
|
704
|
+
formatted_differences += (
|
|
705
|
+
"\nThe visual differences can be found here: "
|
|
706
|
+
+ str(diff_kwargs["tempdir"])
|
|
707
|
+
)
|
|
708
|
+
return super().report(
|
|
709
|
+
ref_file,
|
|
710
|
+
comp_file,
|
|
711
|
+
formatted_differences,
|
|
712
|
+
diff_args,
|
|
713
|
+
diff_kwargs,
|
|
714
|
+
load_kwargs=load_kwargs,
|
|
715
|
+
format_data_kwargs=format_data_kwargs,
|
|
716
|
+
filter_kwargs=filter_kwargs,
|
|
717
|
+
format_diff_kwargs=format_diff_kwargs,
|
|
718
|
+
sort_kwargs=sort_kwargs,
|
|
719
|
+
concat_kwargs=concat_kwargs,
|
|
720
|
+
**kwargs,
|
|
721
|
+
)
|
|
722
|
+
|
|
723
|
+
def format_diff(self, difference, **kwargs):
|
|
724
|
+
"""Format one element difference."""
|
|
725
|
+
return str(difference)
|