pyDiffTools 0.1.28__tar.gz → 0.1.29__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.
- {pydifftools-0.1.28/pyDiffTools.egg-info → pydifftools-0.1.29}/PKG-INFO +3 -1
- {pydifftools-0.1.28 → pydifftools-0.1.29/pyDiffTools.egg-info}/PKG-INFO +3 -1
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pyDiffTools.egg-info/SOURCES.txt +1 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pyDiffTools.egg-info/requires.txt +2 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/command_line.py +72 -1
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/continuous.py +158 -67
- pydifftools-0.1.29/pydifftools/notebook/display.py +67 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/notebook/fast_build.py +340 -22
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pyproject.toml +3 -1
- {pydifftools-0.1.28 → pydifftools-0.1.29}/tests/test_command_line_help.py +64 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/LICENSE.md +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/MANIFEST.in +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/README.rst +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/_quarto.yml +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/1a724af72b16f5a9e607e12b1c721645/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/1b28fc9daac9081847e5161b2c546f8a/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/231f64eee282fa225d1104935cf80a24/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/26e56f6b0ff54851a45145157f2f0dc4/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/311fabd7029ffd050d056e2f316eb50f/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/57da2021e5b156ac3adf01398201c723/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/62b24ea7da75011d92b0f8924faa208d/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/7f1b20d69d889514ab5d1cc92e3cb14f/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/86f74c8c54a87ff892d9b15dd714e8f0/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/88893b4234eac2945d9d6cb2e277f186/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/9a40046ada6f582ee34af00fbdbfb417/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/a1bf4d270d0641ff41faf1d7cce3439a/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/a3789f7d9585a781f2a1c60ce95ff10d/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/be46ecba858d39ad5f0c46902ddf1c02/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/d0cbc57a12f2ccce710a5afd04cc05e7/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/d3e12d320b14228f701231ae32ddd7dd/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/eb434f61555438d020a6970a5dbf9ee8/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/f6b0e73aa7fa029134665d4dde57e096/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/f719a6e4ff09873cb0ffb06ec9d232f9/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/executed/feeee244a7ce3d60e1a227eb604df823/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/example.qmd +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/example.tex +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/index.qmd +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/.jupyter_cache/__version__.txt +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/.jupyter_cache/executed/ca90e4df5f4f0583df6554156a68dc7f/base.ipynb +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/.jupyter_cache/global.db +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/end_vs_he_sketch.jpg +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/independent.qmd +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/index.qmd +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/tasks.qmd +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/test_include.qmd +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/subproject1/tryforerror.qmd +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/example_notebook/project1/test_include.qmd +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pyDiffTools.egg-info/dependency_links.txt +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pyDiffTools.egg-info/entry_points.txt +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pyDiffTools.egg-info/top_level.txt +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/__init__.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/browser_lifecycle.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/check_numbers.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/command_registry.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/comment_functions.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/comment_tags.lua +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/comment_tags_margin.lua +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/comment_tags_no_comments.lua +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/comment_toggle.js +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/comments.css +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/copy_files.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/diff-doc.js +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/doc_contents.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/flowchart/__init__.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/flowchart/dot_to_yaml.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/flowchart/graph.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/flowchart/watch_graph.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/git_gd.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/git_gd_qt.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/html_comments.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/html_uncomments.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/log_example.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/match_spaces.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/notebook/__init__.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/notebook/tex_to_qmd.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/onewordify.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/onewordify_undo.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/outline.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/rearrange_tex.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/searchacro.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/separate_comments.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/split_conflict.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/unseparate_comments.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/update_check.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/wrap_sentences.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/pydifftools/xml2xlsx.vbs +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/setup.cfg +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/tests/test_browser_lifecycle.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/tests/test_continuous_shutdown.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/tests/test_rrng.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/tests/test_tex_to_qmd.py +0 -0
- {pydifftools-0.1.28 → pydifftools-0.1.29}/tests/test_update_check.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyDiffTools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.29
|
|
4
4
|
Summary: Diff tools
|
|
5
5
|
Author: J M Franck
|
|
6
6
|
License: Copyright (c) 2015, jmfranck
|
|
@@ -41,6 +41,8 @@ Requires-Dist: watchdog
|
|
|
41
41
|
Requires-Dist: pydot
|
|
42
42
|
Requires-Dist: python-dateutil
|
|
43
43
|
Requires-Dist: jinja2
|
|
44
|
+
Requires-Dist: ipykernel
|
|
45
|
+
Requires-Dist: matplotlib
|
|
44
46
|
Requires-Dist: nbformat
|
|
45
47
|
Requires-Dist: nbconvert
|
|
46
48
|
Requires-Dist: pygments
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pyDiffTools
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.29
|
|
4
4
|
Summary: Diff tools
|
|
5
5
|
Author: J M Franck
|
|
6
6
|
License: Copyright (c) 2015, jmfranck
|
|
@@ -41,6 +41,8 @@ Requires-Dist: watchdog
|
|
|
41
41
|
Requires-Dist: pydot
|
|
42
42
|
Requires-Dist: python-dateutil
|
|
43
43
|
Requires-Dist: jinja2
|
|
44
|
+
Requires-Dist: ipykernel
|
|
45
|
+
Requires-Dist: matplotlib
|
|
44
46
|
Requires-Dist: nbformat
|
|
45
47
|
Requires-Dist: nbconvert
|
|
46
48
|
Requires-Dist: pygments
|
|
@@ -81,6 +81,7 @@ pydifftools/flowchart/dot_to_yaml.py
|
|
|
81
81
|
pydifftools/flowchart/graph.py
|
|
82
82
|
pydifftools/flowchart/watch_graph.py
|
|
83
83
|
pydifftools/notebook/__init__.py
|
|
84
|
+
pydifftools/notebook/display.py
|
|
84
85
|
pydifftools/notebook/fast_build.py
|
|
85
86
|
pydifftools/notebook/tex_to_qmd.py
|
|
86
87
|
tests/test_browser_lifecycle.py
|
|
@@ -943,11 +943,82 @@ def main(argv=None):
|
|
|
943
943
|
"argument --no-comments: not allowed with argument "
|
|
944
944
|
"--comments-to-margin"
|
|
945
945
|
)
|
|
946
|
+
if (
|
|
947
|
+
namespace.command == "qmdb"
|
|
948
|
+
and namespace.always_code
|
|
949
|
+
and namespace.no_code
|
|
950
|
+
):
|
|
951
|
+
parser._pydifft_subparsers["qmdb"].error(
|
|
952
|
+
"argument --no-code: not allowed with argument --always-code"
|
|
953
|
+
)
|
|
946
954
|
handler = namespace._handler
|
|
947
955
|
handler_kwargs = dict(vars(namespace))
|
|
948
956
|
handler_kwargs.pop("_handler", None)
|
|
949
957
|
handler_kwargs.pop("command", None)
|
|
950
|
-
|
|
958
|
+
# {{{ explain Chrome and ChromeDriver version mismatches
|
|
959
|
+
from selenium.common.exceptions import SessionNotCreatedException
|
|
960
|
+
|
|
961
|
+
try:
|
|
962
|
+
handler(**handler_kwargs)
|
|
963
|
+
except SessionNotCreatedException as exc:
|
|
964
|
+
details = str(exc)
|
|
965
|
+
driver_match = re.search(
|
|
966
|
+
r"ChromeDriver only supports Chrome version (\d+)",
|
|
967
|
+
details,
|
|
968
|
+
)
|
|
969
|
+
browser_match = re.search(
|
|
970
|
+
r"Current browser version is (\d+)",
|
|
971
|
+
details,
|
|
972
|
+
)
|
|
973
|
+
if driver_match is None or browser_match is None:
|
|
974
|
+
raise
|
|
975
|
+
|
|
976
|
+
driver_major = int(driver_match.group(1))
|
|
977
|
+
browser_major = int(browser_match.group(1))
|
|
978
|
+
print(
|
|
979
|
+
"pydifft: Chrome could not start because ChromeDriver "
|
|
980
|
+
f"{driver_major} and Chrome {browser_major} do not match.",
|
|
981
|
+
file=sys.stderr,
|
|
982
|
+
)
|
|
983
|
+
if shutil.which("apt-get") is not None:
|
|
984
|
+
if browser_major < driver_major:
|
|
985
|
+
binary_match = re.search(
|
|
986
|
+
r"binary path ([^;\n]+)",
|
|
987
|
+
details,
|
|
988
|
+
)
|
|
989
|
+
browser_binary = (
|
|
990
|
+
binary_match.group(1) if binary_match is not None else ""
|
|
991
|
+
)
|
|
992
|
+
browser_package = (
|
|
993
|
+
"chromium"
|
|
994
|
+
if "chromium" in browser_binary
|
|
995
|
+
else "google-chrome-stable"
|
|
996
|
+
)
|
|
997
|
+
packages = browser_package
|
|
998
|
+
elif driver_major < browser_major:
|
|
999
|
+
packages = "chromium-driver"
|
|
1000
|
+
else:
|
|
1001
|
+
packages = "google-chrome-stable chromium-driver"
|
|
1002
|
+
print(
|
|
1003
|
+
"Update the older system package:\n"
|
|
1004
|
+
" sudo apt update\n"
|
|
1005
|
+
f" sudo apt install --only-upgrade {packages}",
|
|
1006
|
+
file=sys.stderr,
|
|
1007
|
+
)
|
|
1008
|
+
else:
|
|
1009
|
+
print(
|
|
1010
|
+
"Update the older Chrome or ChromeDriver installation so "
|
|
1011
|
+
"their major versions match.",
|
|
1012
|
+
file=sys.stderr,
|
|
1013
|
+
)
|
|
1014
|
+
print(
|
|
1015
|
+
"Then retry. You can verify the versions with:\n"
|
|
1016
|
+
" google-chrome --version\n"
|
|
1017
|
+
" chromedriver --version",
|
|
1018
|
+
file=sys.stderr,
|
|
1019
|
+
)
|
|
1020
|
+
raise SystemExit(1) from None
|
|
1021
|
+
# }}}
|
|
951
1022
|
|
|
952
1023
|
|
|
953
1024
|
if __name__ == "__main__":
|
|
@@ -52,72 +52,88 @@ def forward_search_listener(stop_event, search_queue):
|
|
|
52
52
|
server.close()
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def
|
|
55
|
+
def _comment_filter_mode(path, packaged_filters=None):
|
|
56
56
|
if not os.path.exists(path):
|
|
57
|
-
return
|
|
57
|
+
return "missing"
|
|
58
|
+
if packaged_filters is None:
|
|
59
|
+
package_dir = os.path.dirname(os.path.abspath(__file__))
|
|
60
|
+
packaged_filters = {
|
|
61
|
+
"default": os.path.join(package_dir, "comment_tags.lua"),
|
|
62
|
+
"margin": os.path.join(package_dir, "comment_tags_margin.lua"),
|
|
63
|
+
"none": os.path.join(package_dir, "comment_tags_no_comments.lua"),
|
|
64
|
+
}
|
|
58
65
|
with open(path, encoding="utf-8") as fp:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if _file_contains_text(path, MARGIN_COMMENTS_FILTER_MARKER):
|
|
66
|
-
return "margin"
|
|
67
|
-
if _file_contains_text(path, NO_COMMENTS_FILTER_MARKER):
|
|
68
|
-
return "none"
|
|
69
|
-
return "default"
|
|
70
|
-
|
|
66
|
+
filter_text = fp.read()
|
|
67
|
+
for mode in ["default", "margin", "none"]:
|
|
68
|
+
with open(packaged_filters[mode], encoding="utf-8") as fp:
|
|
69
|
+
if filter_text == fp.read():
|
|
70
|
+
return mode
|
|
71
|
+
return "custom"
|
|
71
72
|
|
|
72
|
-
def _set_comment_filter_mode(source_dir, mode):
|
|
73
|
-
if mode not in {"default", "margin", "none"}:
|
|
74
|
-
raise ValueError(f"Unknown comment filter mode: {mode}")
|
|
75
|
-
package_dir = os.path.dirname(os.path.abspath(__file__))
|
|
76
|
-
active_filter = os.path.join(source_dir, "comment_tags.lua")
|
|
77
|
-
inactive_filter = os.path.join(source_dir, "comment_tags.lua.inactive")
|
|
78
|
-
packaged_filters = {
|
|
79
|
-
"default": os.path.join(package_dir, "comment_tags.lua"),
|
|
80
|
-
"margin": os.path.join(package_dir, "comment_tags_margin.lua"),
|
|
81
|
-
"none": os.path.join(package_dir, "comment_tags_no_comments.lua"),
|
|
82
|
-
}
|
|
83
73
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
74
|
+
def _confirm_restore_comment_filter(active_mode):
|
|
75
|
+
if active_mode == "none":
|
|
76
|
+
message = (
|
|
77
|
+
"The current lua filter is the one that does not show comments, "
|
|
78
|
+
"but you ran without the --no-comments flag.\n\n"
|
|
79
|
+
"Note that you have not locally edited the filter relative to "
|
|
80
|
+
"the library default.\n\n"
|
|
81
|
+
"Do you want to keep the current filter, or restore the library "
|
|
82
|
+
"default that shows comments?"
|
|
83
|
+
)
|
|
84
|
+
default_choice = "restore"
|
|
85
|
+
elif active_mode == "custom":
|
|
86
|
+
message = (
|
|
87
|
+
"The current lua filter does not match the pyDiffTools library "
|
|
88
|
+
"default or the no-comments filter, but you ran without the "
|
|
89
|
+
"--no-comments flag.\n\n"
|
|
90
|
+
"Note that this looks like a locally edited filter.\n\n"
|
|
91
|
+
"Do you want to keep the current filter, or restore the library "
|
|
92
|
+
"default that shows comments?"
|
|
93
|
+
)
|
|
94
|
+
default_choice = "keep"
|
|
95
|
+
else:
|
|
96
|
+
raise ValueError(
|
|
97
|
+
"Comment filter restore prompt is only valid for custom or "
|
|
98
|
+
f"no-comments filters, not {active_mode!r}"
|
|
99
|
+
)
|
|
100
|
+
prompt_script = """
|
|
101
|
+
import sys
|
|
102
|
+
from PySide6.QtWidgets import QApplication, QMessageBox
|
|
108
103
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
104
|
+
app = QApplication(sys.argv[:1])
|
|
105
|
+
box = QMessageBox()
|
|
106
|
+
box.setWindowTitle("pydifft cpb")
|
|
107
|
+
box.setIcon(QMessageBox.Icon.Question)
|
|
108
|
+
box.setText(sys.argv[1])
|
|
109
|
+
keep_button = box.addButton(
|
|
110
|
+
"Keep current filter", QMessageBox.ButtonRole.RejectRole
|
|
111
|
+
)
|
|
112
|
+
restore_button = box.addButton(
|
|
113
|
+
"Restore library default", QMessageBox.ButtonRole.AcceptRole
|
|
114
|
+
)
|
|
115
|
+
if sys.argv[2] == "restore":
|
|
116
|
+
box.setDefaultButton(restore_button)
|
|
117
|
+
else:
|
|
118
|
+
box.setDefaultButton(keep_button)
|
|
119
|
+
box.exec()
|
|
120
|
+
if box.clickedButton() is restore_button:
|
|
121
|
+
sys.exit(0)
|
|
122
|
+
sys.exit(1)
|
|
123
|
+
"""
|
|
124
|
+
result = subprocess.run(
|
|
125
|
+
[sys.executable, "-c", prompt_script, message, default_choice],
|
|
126
|
+
capture_output=True,
|
|
127
|
+
text=True,
|
|
128
|
+
)
|
|
129
|
+
if result.returncode == 0:
|
|
130
|
+
return True
|
|
131
|
+
if result.returncode == 1:
|
|
132
|
+
return False
|
|
133
|
+
stderr = result.stderr.strip()
|
|
134
|
+
if stderr:
|
|
135
|
+
raise RuntimeError(f"pydifft cpb filter dialog failed: {stderr}")
|
|
136
|
+
raise RuntimeError("pydifft cpb filter dialog failed.")
|
|
121
137
|
|
|
122
138
|
|
|
123
139
|
def run_pandoc(
|
|
@@ -168,10 +184,87 @@ def run_pandoc(
|
|
|
168
184
|
):
|
|
169
185
|
# Keep the active comment filter in the markdown directory so pandoc
|
|
170
186
|
# picks it up alongside other user-supplied project filters.
|
|
171
|
-
|
|
187
|
+
# {{{ select the active comment_tags.lua filter
|
|
188
|
+
package_dir = os.path.dirname(os.path.abspath(__file__))
|
|
189
|
+
active_filter = os.path.join(source_dir, "comment_tags.lua")
|
|
190
|
+
inactive_filter = os.path.join(
|
|
191
|
+
source_dir, "comment_tags.lua.inactive"
|
|
192
|
+
)
|
|
193
|
+
packaged_filters = {
|
|
194
|
+
"default": os.path.join(package_dir, "comment_tags.lua"),
|
|
195
|
+
"margin": os.path.join(package_dir, "comment_tags_margin.lua"),
|
|
196
|
+
"none": os.path.join(package_dir, "comment_tags_no_comments.lua"),
|
|
197
|
+
}
|
|
198
|
+
active_mode = _comment_filter_mode(active_filter, packaged_filters)
|
|
199
|
+
inactive_mode = _comment_filter_mode(inactive_filter, packaged_filters)
|
|
200
|
+
|
|
201
|
+
if comment_filter_mode == "default":
|
|
202
|
+
if active_mode == "default":
|
|
203
|
+
effective_filter_mode = "default"
|
|
204
|
+
elif active_mode == "none":
|
|
205
|
+
if _confirm_restore_comment_filter("none"):
|
|
206
|
+
shutil.copy2(
|
|
207
|
+
packaged_filters["default"], active_filter
|
|
208
|
+
)
|
|
209
|
+
effective_filter_mode = "default"
|
|
210
|
+
else:
|
|
211
|
+
effective_filter_mode = "none"
|
|
212
|
+
elif active_mode == "custom":
|
|
213
|
+
if _confirm_restore_comment_filter("custom"):
|
|
214
|
+
shutil.copy2(
|
|
215
|
+
packaged_filters["default"], active_filter
|
|
216
|
+
)
|
|
217
|
+
effective_filter_mode = "default"
|
|
218
|
+
else:
|
|
219
|
+
effective_filter_mode = "custom"
|
|
220
|
+
elif active_mode == "margin":
|
|
221
|
+
if inactive_mode in {"default", "custom"}:
|
|
222
|
+
temp_filter = active_filter + ".swap_tmp"
|
|
223
|
+
os.replace(active_filter, temp_filter)
|
|
224
|
+
os.replace(inactive_filter, active_filter)
|
|
225
|
+
os.replace(temp_filter, inactive_filter)
|
|
226
|
+
effective_filter_mode = inactive_mode
|
|
227
|
+
else:
|
|
228
|
+
os.replace(active_filter, inactive_filter)
|
|
229
|
+
shutil.copy2(
|
|
230
|
+
packaged_filters["default"], active_filter
|
|
231
|
+
)
|
|
232
|
+
effective_filter_mode = "default"
|
|
233
|
+
elif active_mode == "missing":
|
|
234
|
+
if inactive_mode in {"default", "custom"}:
|
|
235
|
+
os.replace(inactive_filter, active_filter)
|
|
236
|
+
effective_filter_mode = inactive_mode
|
|
237
|
+
else:
|
|
238
|
+
shutil.copy2(
|
|
239
|
+
packaged_filters["default"], active_filter
|
|
240
|
+
)
|
|
241
|
+
effective_filter_mode = "default"
|
|
242
|
+
else:
|
|
243
|
+
shutil.copy2(packaged_filters["default"], active_filter)
|
|
244
|
+
effective_filter_mode = "default"
|
|
245
|
+
else:
|
|
246
|
+
effective_filter_mode = comment_filter_mode
|
|
247
|
+
if active_mode == comment_filter_mode:
|
|
248
|
+
pass
|
|
249
|
+
elif active_mode in {"default", "custom"}:
|
|
250
|
+
os.replace(active_filter, inactive_filter)
|
|
251
|
+
shutil.copy2(
|
|
252
|
+
packaged_filters[comment_filter_mode], active_filter
|
|
253
|
+
)
|
|
254
|
+
else:
|
|
255
|
+
if active_mode == "missing" and inactive_mode not in {
|
|
256
|
+
"default",
|
|
257
|
+
"custom",
|
|
258
|
+
}:
|
|
259
|
+
shutil.copy2(
|
|
260
|
+
packaged_filters["default"], inactive_filter
|
|
261
|
+
)
|
|
262
|
+
shutil.copy2(
|
|
263
|
+
packaged_filters[comment_filter_mode], active_filter
|
|
264
|
+
)
|
|
265
|
+
# }}}
|
|
172
266
|
# Only copy the comment UI assets when comments should be rendered.
|
|
173
|
-
if
|
|
174
|
-
package_dir = os.path.dirname(os.path.abspath(__file__))
|
|
267
|
+
if effective_filter_mode != "none":
|
|
175
268
|
for asset_name in ["comments.css", "comment_toggle.js"]:
|
|
176
269
|
target_path = os.path.join(source_dir, asset_name)
|
|
177
270
|
if not os.path.exists(target_path):
|
|
@@ -483,6 +576,4 @@ def cpb(filename, comments_to_margin=False, no_comments=False):
|
|
|
483
576
|
|
|
484
577
|
|
|
485
578
|
if __name__ == "__main__":
|
|
486
|
-
|
|
487
|
-
cpb(filename)
|
|
488
|
-
# Open the HTML file in the default web browser
|
|
579
|
+
raise SystemExit("Use `pydifft cpb <filename.md>` instead.")
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Small display helpers for fast notebook builds."""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class _NotebookCapture:
|
|
5
|
+
"""Emit notebook content in an explicit order."""
|
|
6
|
+
|
|
7
|
+
def __init__(self):
|
|
8
|
+
self._figures = []
|
|
9
|
+
|
|
10
|
+
def __enter__(self):
|
|
11
|
+
return self
|
|
12
|
+
|
|
13
|
+
def __exit__(self, exc_type, exc, tb):
|
|
14
|
+
for fig in self._figures:
|
|
15
|
+
self._close_figure(fig)
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
def md(self, text):
|
|
19
|
+
"""Display markdown text as a Jupyter Markdown MIME bundle."""
|
|
20
|
+
from IPython.display import Markdown, display
|
|
21
|
+
|
|
22
|
+
display(Markdown(text))
|
|
23
|
+
|
|
24
|
+
def fig(self, obj=None):
|
|
25
|
+
"""Display a Matplotlib figure-like object and close it afterward."""
|
|
26
|
+
from io import BytesIO
|
|
27
|
+
|
|
28
|
+
from IPython.display import Image, display
|
|
29
|
+
|
|
30
|
+
fig = self._figure_from_object(obj)
|
|
31
|
+
if hasattr(fig, "savefig"):
|
|
32
|
+
data = BytesIO()
|
|
33
|
+
fig.savefig(data, format="png", bbox_inches="tight")
|
|
34
|
+
display(Image(data=data.getvalue()))
|
|
35
|
+
else:
|
|
36
|
+
display(fig)
|
|
37
|
+
self._figures.append(fig)
|
|
38
|
+
self._close_figure(fig)
|
|
39
|
+
|
|
40
|
+
def _figure_from_object(self, obj):
|
|
41
|
+
import matplotlib.pyplot as plt
|
|
42
|
+
|
|
43
|
+
if obj is None:
|
|
44
|
+
return plt.gcf()
|
|
45
|
+
if isinstance(obj, (list, tuple)):
|
|
46
|
+
if not obj:
|
|
47
|
+
raise ValueError("cannot display an empty figure object list")
|
|
48
|
+
return self._figure_from_object(obj[0])
|
|
49
|
+
if hasattr(obj, "get_figure"):
|
|
50
|
+
fig = obj.get_figure()
|
|
51
|
+
if fig is not None:
|
|
52
|
+
return fig
|
|
53
|
+
if hasattr(obj, "figure"):
|
|
54
|
+
fig = obj.figure
|
|
55
|
+
if fig is not None and fig is not obj:
|
|
56
|
+
return fig
|
|
57
|
+
return obj
|
|
58
|
+
|
|
59
|
+
def _close_figure(self, fig):
|
|
60
|
+
import matplotlib.pyplot as plt
|
|
61
|
+
|
|
62
|
+
plt.close(fig)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def nb_capture():
|
|
66
|
+
"""Return an ordered notebook output capture context."""
|
|
67
|
+
return _NotebookCapture()
|