pyDiffTools 0.1.8__py3-none-any.whl
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/__init__.py +11 -0
- pydifftools/check_numbers.py +70 -0
- pydifftools/command_line.py +747 -0
- pydifftools/command_registry.py +65 -0
- pydifftools/comment_functions.py +39 -0
- pydifftools/continuous.py +194 -0
- pydifftools/copy_files.py +75 -0
- pydifftools/diff-doc.js +193 -0
- pydifftools/doc_contents.py +147 -0
- pydifftools/flowchart/__init__.py +15 -0
- pydifftools/flowchart/dot_to_yaml.py +114 -0
- pydifftools/flowchart/graph.py +620 -0
- pydifftools/flowchart/watch_graph.py +168 -0
- pydifftools/html_comments.py +33 -0
- pydifftools/html_uncomments.py +524 -0
- pydifftools/match_spaces.py +235 -0
- pydifftools/notebook/__init__.py +0 -0
- pydifftools/notebook/fast_build.py +1502 -0
- pydifftools/notebook/tex_to_qmd.py +319 -0
- pydifftools/onewordify.py +149 -0
- pydifftools/onewordify_undo.py +54 -0
- pydifftools/outline.py +173 -0
- pydifftools/rearrange_tex.py +188 -0
- pydifftools/searchacro.py +80 -0
- pydifftools/separate_comments.py +73 -0
- pydifftools/split_conflict.py +213 -0
- pydifftools/unseparate_comments.py +69 -0
- pydifftools/update_check.py +31 -0
- pydifftools/wrap_sentences.py +501 -0
- pydifftools/xml2xlsx.vbs +33 -0
- pydifftools-0.1.8.dist-info/METADATA +146 -0
- pydifftools-0.1.8.dist-info/RECORD +36 -0
- pydifftools-0.1.8.dist-info/WHEEL +5 -0
- pydifftools-0.1.8.dist-info/entry_points.txt +2 -0
- pydifftools-0.1.8.dist-info/licenses/LICENSE.md +28 -0
- pydifftools-0.1.8.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import time
|
|
3
|
+
import shutil
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from watchdog.events import FileSystemEventHandler
|
|
6
|
+
from watchdog.observers import Observer
|
|
7
|
+
from pydifftools.command_registry import register_command
|
|
8
|
+
from .graph import write_dot_from_yaml
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _reload_svg(driver, svg_file: Path) -> None:
|
|
12
|
+
"""Refresh the embedded SVG while preserving zoom and scroll."""
|
|
13
|
+
zoom = driver.execute_script("return window.visualViewport.scale")
|
|
14
|
+
scroll_x = driver.execute_script("return window.scrollX")
|
|
15
|
+
scroll_y = driver.execute_script("return window.scrollY")
|
|
16
|
+
svg_uri = svg_file.resolve().as_uri() + f"?t={time.time()}"
|
|
17
|
+
driver.execute_async_script(
|
|
18
|
+
"const [src,z,x,y,done]=arguments;const"
|
|
19
|
+
" s=document.getElementById('svg-view');s.onload=function()"
|
|
20
|
+
"{document.body.style.zoom=z;"
|
|
21
|
+
" window.scrollTo(x,y); done();};s.setAttribute('src', src);",
|
|
22
|
+
svg_uri,
|
|
23
|
+
zoom,
|
|
24
|
+
scroll_x,
|
|
25
|
+
scroll_y,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def build_graph(
|
|
30
|
+
yaml_file,
|
|
31
|
+
dot_file,
|
|
32
|
+
svg_file,
|
|
33
|
+
wrap_width,
|
|
34
|
+
order_by_date=False,
|
|
35
|
+
prev_data=None,
|
|
36
|
+
):
|
|
37
|
+
# Graphviz is required for dot -> svg rendering.
|
|
38
|
+
if shutil.which("dot") is None:
|
|
39
|
+
raise RuntimeError(
|
|
40
|
+
"Graphviz is required to render flowcharts. Install it so the"
|
|
41
|
+
" 'dot' executable is available on your PATH."
|
|
42
|
+
)
|
|
43
|
+
data = write_dot_from_yaml(
|
|
44
|
+
str(yaml_file),
|
|
45
|
+
str(dot_file),
|
|
46
|
+
wrap_width=wrap_width,
|
|
47
|
+
order_by_date=order_by_date,
|
|
48
|
+
old_data=prev_data,
|
|
49
|
+
validate_due_dates=True,
|
|
50
|
+
)
|
|
51
|
+
subprocess.run(
|
|
52
|
+
["dot", "-Tsvg", str(dot_file), "-o", str(svg_file)],
|
|
53
|
+
check=True,
|
|
54
|
+
)
|
|
55
|
+
return data
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
class GraphEventHandler(FileSystemEventHandler):
|
|
59
|
+
def __init__(
|
|
60
|
+
self,
|
|
61
|
+
yaml_file,
|
|
62
|
+
dot_file,
|
|
63
|
+
svg_file,
|
|
64
|
+
driver,
|
|
65
|
+
wrap_width,
|
|
66
|
+
data,
|
|
67
|
+
order_by_date=False,
|
|
68
|
+
debounce=0.25,
|
|
69
|
+
):
|
|
70
|
+
self.yaml_file = Path(yaml_file)
|
|
71
|
+
self.dot_file = Path(dot_file)
|
|
72
|
+
self.svg_file = Path(svg_file)
|
|
73
|
+
self.driver = driver
|
|
74
|
+
self.wrap_width = wrap_width
|
|
75
|
+
self.data = data
|
|
76
|
+
self.order_by_date = order_by_date
|
|
77
|
+
self.debounce = debounce
|
|
78
|
+
self._last_handled = 0.0
|
|
79
|
+
self._last_mtime = None
|
|
80
|
+
|
|
81
|
+
def on_modified(self, event):
|
|
82
|
+
if Path(event.src_path) == self.yaml_file:
|
|
83
|
+
mtime = self.yaml_file.stat().st_mtime
|
|
84
|
+
if self._last_mtime is not None and mtime == self._last_mtime:
|
|
85
|
+
return
|
|
86
|
+
now = time.time()
|
|
87
|
+
if now - self._last_handled < self.debounce:
|
|
88
|
+
return
|
|
89
|
+
self._last_handled = now
|
|
90
|
+
self.data = build_graph(
|
|
91
|
+
self.yaml_file,
|
|
92
|
+
self.dot_file,
|
|
93
|
+
self.svg_file,
|
|
94
|
+
self.wrap_width,
|
|
95
|
+
self.order_by_date,
|
|
96
|
+
self.data,
|
|
97
|
+
)
|
|
98
|
+
_reload_svg(self.driver, self.svg_file)
|
|
99
|
+
self._last_mtime = self.yaml_file.stat().st_mtime
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@register_command(
|
|
103
|
+
"Watch a flowchart YAML file, rebuild DOT/SVG output, and open the"
|
|
104
|
+
" preview",
|
|
105
|
+
help={
|
|
106
|
+
"yaml": "Path to the flowchart YAML file",
|
|
107
|
+
"wrap_width": "Line wrap width used when generating node labels",
|
|
108
|
+
"d": "Render nodes by date without showing connections",
|
|
109
|
+
},
|
|
110
|
+
)
|
|
111
|
+
def wgrph(yaml, wrap_width=55, d=False):
|
|
112
|
+
# Selenium is only required when actually launching the watcher, so it is
|
|
113
|
+
# imported here to avoid breaking the command-line tools when the optional
|
|
114
|
+
# dependency is not installed.
|
|
115
|
+
try:
|
|
116
|
+
from selenium import webdriver
|
|
117
|
+
from selenium.webdriver.chrome.options import Options
|
|
118
|
+
from selenium.common.exceptions import (
|
|
119
|
+
WebDriverException,
|
|
120
|
+
NoSuchWindowException,
|
|
121
|
+
)
|
|
122
|
+
except ImportError as exc:
|
|
123
|
+
raise ImportError(
|
|
124
|
+
"The 'watch_graph' command requires the 'selenium' package to be"
|
|
125
|
+
" installed."
|
|
126
|
+
) from exc
|
|
127
|
+
|
|
128
|
+
yaml_file = Path(yaml)
|
|
129
|
+
if not yaml_file.exists():
|
|
130
|
+
raise FileNotFoundError(f"YAML file not found: {yaml_file}")
|
|
131
|
+
|
|
132
|
+
dot_file = yaml_file.with_suffix(".dot")
|
|
133
|
+
svg_file = yaml_file.with_suffix(".svg")
|
|
134
|
+
html_file = yaml_file.with_suffix(".html")
|
|
135
|
+
|
|
136
|
+
# Use date ordering when requested so boxes appear in calendar order.
|
|
137
|
+
data = build_graph(yaml_file, dot_file, svg_file, wrap_width, d)
|
|
138
|
+
html_file.write_text(
|
|
139
|
+
"<html><body style='margin:0'><embed id='svg-view'"
|
|
140
|
+
" type='image/svg+xml'"
|
|
141
|
+
f" src='{svg_file.name}?t={time.time()}'/></body></html>"
|
|
142
|
+
)
|
|
143
|
+
options = Options()
|
|
144
|
+
driver = webdriver.Chrome(options=options)
|
|
145
|
+
driver.get(html_file.resolve().as_uri())
|
|
146
|
+
event_handler = GraphEventHandler(
|
|
147
|
+
yaml_file, dot_file, svg_file, driver, wrap_width, data, d
|
|
148
|
+
)
|
|
149
|
+
observer = Observer()
|
|
150
|
+
observer.schedule(event_handler, yaml_file.parent, recursive=False)
|
|
151
|
+
observer.start()
|
|
152
|
+
try:
|
|
153
|
+
while True:
|
|
154
|
+
try:
|
|
155
|
+
_ = driver.window_handles
|
|
156
|
+
driver.execute_script("return 1")
|
|
157
|
+
except (NoSuchWindowException, WebDriverException):
|
|
158
|
+
break
|
|
159
|
+
time.sleep(1)
|
|
160
|
+
except KeyboardInterrupt:
|
|
161
|
+
pass
|
|
162
|
+
finally:
|
|
163
|
+
observer.stop()
|
|
164
|
+
observer.join()
|
|
165
|
+
try:
|
|
166
|
+
driver.quit()
|
|
167
|
+
except Exception:
|
|
168
|
+
pass
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# again rerun
|
|
2
|
+
from lxml import html, etree
|
|
3
|
+
import os
|
|
4
|
+
from pyspecdata.fornotebook import *
|
|
5
|
+
from pyspecdata import *
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
fp = open(sys.argv[1], "r")
|
|
9
|
+
content = fp.read()
|
|
10
|
+
fp.close()
|
|
11
|
+
doc = html.fromstring(content)
|
|
12
|
+
commentlabel_re = re.compile(r"\[([A-Z]+)([0-9])\]")
|
|
13
|
+
comment_dict = {}
|
|
14
|
+
# for j in doc.xpath('descendant::*[@style="mso-element:comment"]'):
|
|
15
|
+
newlist = []
|
|
16
|
+
thisbody = doc.find("body")
|
|
17
|
+
print("I found the body", lsafen(thisbody))
|
|
18
|
+
commentlist = etree.Element("div", style="mso-element:comment-list")
|
|
19
|
+
for j in doc.xpath('//span[@style="mso-element:comment"]'):
|
|
20
|
+
# for j in doc.xpath('//span[@style="mso-element:comment"]'):
|
|
21
|
+
# print 'found span with style:\n\n',lsafen(html.tostring(j),wrap = 60)
|
|
22
|
+
# if j.attrib['style'] == 'mso-element:comment':
|
|
23
|
+
print("found span with style:\n\n", lsafen(j.attrib, wrap=60))
|
|
24
|
+
newlist.append(j)
|
|
25
|
+
j.drop_tree()
|
|
26
|
+
commentlist.append(j)
|
|
27
|
+
thisbody.append(commentlist)
|
|
28
|
+
# print lsafen(map(html.tostring,newlist),wrap = 60)
|
|
29
|
+
newfile = re.sub(r"(.*)(\.htm.*)", r"\1_htmlcomm\2", sys.argv[1])
|
|
30
|
+
fp = open(newfile, "w")
|
|
31
|
+
content = html.tostring(doc)
|
|
32
|
+
fp.write(content)
|
|
33
|
+
fp.close()
|